diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinGameRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinGameRenderer.java index 04e93ab8bf5..e7b8cfab46c 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinGameRenderer.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinGameRenderer.java @@ -33,6 +33,7 @@ import net.ccbluex.liquidbounce.interfaces.LightmapTextureManagerAddition; import net.ccbluex.liquidbounce.interfaces.PostEffectPassTextureAddition; import net.ccbluex.liquidbounce.render.engine.UIRenderer; +import net.ccbluex.liquidbounce.render.shader.shaders.OutlineEffectShader; import net.ccbluex.liquidbounce.utils.aiming.RaytracingExtensionsKt; import net.ccbluex.liquidbounce.utils.aiming.Rotation; import net.ccbluex.liquidbounce.utils.aiming.RotationManager; @@ -145,6 +146,22 @@ public void hookWorldRender(RenderTickCounter tickCounter, CallbackInfo ci, @Loc EventManager.INSTANCE.callEvent(new WorldRenderEvent(newMatStack, this.camera, tickCounter.getTickDelta(false))); } + @Inject(method = "renderHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/LightmapTextureManager;enable()V", shift = At.Shift.AFTER)) + public void prepareItemCharms(Camera camera, float tickDelta, Matrix4f matrix4f, CallbackInfo ci) { + if (ModuleItemChams.INSTANCE.getRunning()) { + ModuleItemChams.INSTANCE.setData(); + OutlineEffectShader.INSTANCE.prepare(); + } + } + + @Inject(method = "renderHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;Lnet/minecraft/client/network/ClientPlayerEntity;I)V", shift = At.Shift.AFTER)) + public void drawItemCharms(Camera camera, float tickDelta, Matrix4f matrix4f, CallbackInfo ci) { + if (ModuleItemChams.INSTANCE.getActive()) { + ModuleItemChams.INSTANCE.setActive(false); + OutlineEffectShader.INSTANCE.apply(); + } + } + /** * Hook screen render event */ diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt index 708d20e26dd..627e10cc6b9 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt @@ -329,6 +329,7 @@ object ModuleManager : EventListener, Iterable by modules { ModuleXRay, ModuleDebug, ModuleZoom, + ModuleItemChams, // World ModuleAutoBuild, diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleItemChams.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleItemChams.kt new file mode 100644 index 00000000000..c9e0090df17 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleItemChams.kt @@ -0,0 +1,59 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.features.module.modules.render + +import net.ccbluex.liquidbounce.features.module.Category +import net.ccbluex.liquidbounce.features.module.ClientModule +import net.ccbluex.liquidbounce.injection.mixins.minecraft.render.MixinGameRenderer +import net.ccbluex.liquidbounce.render.engine.Color4b +import net.ccbluex.liquidbounce.render.shader.shaders.OutlineEffectShaderData + +/** + * Module ItemChams + * + * Applies visual effects to your held items. + * + * [MixinGameRenderer] + * + * @author ccetl + */ +object ModuleItemChams : ClientModule("ItemChams", Category.RENDER) { + + private val blendColor by color("BlendColor", Color4b(0, 64, 255, 186)) + private val alpha by int("Alpha", 95, 1..255) + private val glowColor by color("GlowColor", Color4b(0, 64, 255, 15)) + private val layers by int("Layers", 3, 1..10) + private val layerSize by float("LayerSize", 1.91f, 1f..5f) + private val falloff by float("Falloff", 6.83f, 0f..20f) + + var active = false + + fun setData() { + active = true + with(OutlineEffectShaderData) { + falloff = ModuleItemChams.falloff + sampleMul = layerSize + layerCount = layers + glowColor = ModuleItemChams.glowColor + blendColor = ModuleItemChams.blendColor + alpha = ModuleItemChams.alpha / 255f + } + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/nuker/mode/LegitNukerMode.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/nuker/mode/LegitNukerMode.kt index be0b13be797..7286e47220b 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/nuker/mode/LegitNukerMode.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/nuker/mode/LegitNukerMode.kt @@ -1,3 +1,21 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ package net.ccbluex.liquidbounce.features.module.modules.world.nuker.mode import net.ccbluex.liquidbounce.config.types.Choice diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/integration/theme/ThemeManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/integration/theme/ThemeManager.kt index 5e35aef7ec7..d3cb822ad42 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/integration/theme/ThemeManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/integration/theme/ThemeManager.kt @@ -35,7 +35,7 @@ import net.ccbluex.liquidbounce.integration.interop.ClientInteropServer import net.ccbluex.liquidbounce.integration.theme.component.Component import net.ccbluex.liquidbounce.integration.theme.component.ComponentOverlay import net.ccbluex.liquidbounce.integration.theme.component.ComponentType -import net.ccbluex.liquidbounce.render.shader.Shader +import net.ccbluex.liquidbounce.render.shader.CanvasShader import net.ccbluex.liquidbounce.utils.client.logger import net.ccbluex.liquidbounce.utils.client.mc import net.ccbluex.liquidbounce.utils.io.extractZip @@ -202,7 +202,7 @@ class Theme(val name: String) { get() = File(folder, "background.frag") private val backgroundImage: File get() = File(folder, "background.png") - var compiledShaderBackground: Shader? = null + var compiledShaderBackground: CanvasShader? = null private set var loadedBackgroundImage: Identifier? = null private set @@ -213,7 +213,7 @@ class Theme(val name: String) { } readShaderBackground()?.let { shaderBackground -> - compiledShaderBackground = Shader(resourceToString("/assets/liquidbounce/shaders/vertex.vert"), + compiledShaderBackground = CanvasShader(resourceToString("/assets/liquidbounce/shaders/vertex.vert"), shaderBackground) logger.info("Compiled background shader for theme $name") return true diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/render/engine/RenderTasks.kt b/src/main/kotlin/net/ccbluex/liquidbounce/render/engine/RenderTasks.kt index 8b76767aef3..c63ce309fb4 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/render/engine/RenderTasks.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/render/engine/RenderTasks.kt @@ -20,6 +20,7 @@ package net.ccbluex.liquidbounce.render.engine import net.minecraft.util.math.Vec3d import net.minecraft.util.math.Vec3i +import org.lwjgl.opengl.GL20 import java.awt.Color import java.nio.ByteBuffer import kotlin.math.cos @@ -186,4 +187,8 @@ data class Color4b(val r: Int, val g: Int, val b: Int, val a: Int) { private fun darkerChannel(value: Int) = (value * 0.7).toInt().coerceAtLeast(0) + fun putToUniform(pointer: Int) { + GL20.glUniform4f(pointer, r / 255f, g / 255f, b / 255f, a / 255f) + } + } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/CanvasShader.kt b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/CanvasShader.kt new file mode 100644 index 00000000000..5ffb63bf32e --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/CanvasShader.kt @@ -0,0 +1,93 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.render.shader + +import net.ccbluex.liquidbounce.utils.client.mc +import net.minecraft.client.gl.GlUniform +import net.minecraft.client.gl.VertexBuffer +import net.minecraft.client.render.Tessellator +import net.minecraft.client.render.VertexFormat +import net.minecraft.client.render.VertexFormats +import org.lwjgl.opengl.GL30 + +/** + * A GLSL shader renderer. Takes a vertex and fragment shader and renders it to the canvas. + * + * Inspired from the GLSL Panorama Shader Mod + * https://github.com/magistermaks/mod-glsl + */ +class CanvasShader(vertex: String, fragment: String) : Shader(vertex, fragment) { + + private var canvas = ScalableCanvas() + private var buffer = VertexBuffer(VertexBuffer.Usage.DYNAMIC) + + private val timeLocation: Int + private val mouseLocation: Int + private val resolutionLocation: Int + + private var time = 0f + + init { + // bake buffer data + val builder = Tessellator.getInstance() + val buffer = builder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR) + buffer.vertex(-1.0f, -1.0f, 1.0f).texture(0f, 0f) + .color(1f, 1f, 1f, 1f) + buffer.vertex(1.0f, -1.0f, 1.0f).texture(1f, 0f) + .color(1f, 1f, 1f, 1f) + buffer.vertex(1.0f, 1.0f, 1.0f).texture(1f, 1f) + .color(1f, 1f, 1f, 1f) + buffer.vertex(-1.0f, 1.0f, 1.0f).texture(0f, 1f) + .color(1f, 1f, 1f, 1f) + + this.buffer.bind() + this.buffer.upload(buffer.end()) + VertexBuffer.unbind() + + // get uniform pointers + timeLocation = GlUniform.getUniformLocation(program, "time") + mouseLocation = GlUniform.getUniformLocation(program, "mouse") + resolutionLocation = GlUniform.getUniformLocation(program, "resolution") + } + + fun draw(mouseX: Int, mouseY: Int, delta: Float) { + super.use() + + canvas.resize(mc.window.framebufferWidth, mc.window.framebufferHeight) + canvas.write() + + // update uniforms + GL30.glUniform1f(timeLocation, time) + time += (delta / 10f) + GL30.glUniform2f(mouseLocation, mouseX.toFloat(), mouseY.toFloat()) + GL30.glUniform2f(resolutionLocation, canvas.width().toFloat(), canvas.height().toFloat()) + + // draw + buffer.bind() + buffer.draw() + canvas.blit(buffer) + } + + override fun close() { + super.close() + buffer.close() + canvas.close() + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/FramebufferShader.kt b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/FramebufferShader.kt new file mode 100644 index 00000000000..a149cbf9b80 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/FramebufferShader.kt @@ -0,0 +1,129 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.render.shader + +import com.mojang.blaze3d.platform.GlStateManager +import com.mojang.blaze3d.systems.RenderSystem +import net.ccbluex.liquidbounce.features.module.MinecraftShortcuts +import net.minecraft.client.gl.SimpleFramebuffer +import net.minecraft.client.gl.VertexBuffer +import net.minecraft.client.render.Tessellator +import net.minecraft.client.render.VertexFormat +import net.minecraft.client.render.VertexFormats +import org.lwjgl.opengl.GL11 +import org.lwjgl.opengl.GL13 +import java.io.Closeable + +/** + * @author ccetl + */ +open class FramebufferShader(vararg val shaders: Shader) : MinecraftShortcuts, Closeable { + + private val framebuffers = mutableListOf() + private var buffer = VertexBuffer(VertexBuffer.Usage.DYNAMIC) + + init { + val width = mc.window.framebufferWidth + val height = mc.window.framebufferHeight + shaders.forEach { _ -> + val framebuffer = SimpleFramebuffer(width, height, false, false) + framebuffer.setClearColor(0f, 0f, 0f, 0f) + framebuffers.add(framebuffer) + } + + val builder = Tessellator.getInstance() + val bufferBuilder = builder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE) + bufferBuilder.vertex(-1f, -1f, 0f).texture(0f, 0f) + bufferBuilder.vertex(1f, -1f, 0f).texture(1f, 0f) + bufferBuilder.vertex(1f, 1f, 0f).texture(1f, 1f) + bufferBuilder.vertex(-1f, 1f, 0f).texture(0f, 1f) + buffer.bind() + buffer.upload(bufferBuilder.end()) + VertexBuffer.unbind() + } + + fun prepare() { + val width = mc.window.framebufferWidth + val height = mc.window.framebufferHeight + framebuffers.forEach { + if (it.textureWidth != width || it.textureHeight != height) { + it.resize(width, height, false) + } + } + + framebuffers[0].clear(false) + framebuffers[0].beginWrite(true) + } + + fun apply() { + val active = GlStateManager._getActiveTexture() + val alphaTest = GL11.glIsEnabled(GL11.GL_ALPHA_TEST) + + GL11.glDisable(GL11.GL_ALPHA_TEST) + GlStateManager._bindTexture(0) + + RenderSystem.disableDepthTest() + RenderSystem.enableBlend() + RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA) + + RenderSystem.setShaderColor(1f, 1f, 1f, 0f) + shaders.forEachIndexed { i, shader -> + val inputFramebuffer = framebuffers.getOrNull(i) ?: framebuffers.first() + val outputFramebuffer = framebuffers.getOrNull(i + 1) + + outputFramebuffer?.clear(false) + outputFramebuffer?.beginWrite(true) ?: mc.framebuffer.beginWrite(false) + + GlStateManager._activeTexture(GL13.GL_TEXTURE0 + i) + GlStateManager._bindTexture(inputFramebuffer.colorAttachment) + + shader.use() + + buffer.bind() + buffer.draw() + VertexBuffer.unbind() + + shader.stop() + } + + shaders.indices.forEach { + GlStateManager._activeTexture(GL13.GL_TEXTURE0 + it) + GlStateManager._bindTexture(0) + } + + RenderSystem.enableDepthTest() + GlStateManager._activeTexture(active) + if (alphaTest) { + GL11.glEnable(GL11.GL_ALPHA_TEST) + } + } + + fun render(drawAction: () -> Unit) { + prepare() + drawAction() + apply() + } + + override fun close() { + shaders.forEach { it.close() } + buffer.close() + framebuffers.forEach { it.delete() } + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/Shader.kt b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/Shader.kt index bdffdff810c..33ea3b55305 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/Shader.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/Shader.kt @@ -1,51 +1,37 @@ /* - * LiquidBounce Hacked Client - * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. - * https://github.com/CCBlueX/LiquidBounce/ + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . */ package net.ccbluex.liquidbounce.render.shader import com.mojang.blaze3d.platform.GlConst import com.mojang.blaze3d.platform.GlStateManager -import net.ccbluex.liquidbounce.utils.client.mc import net.minecraft.client.gl.GlProgramManager -import net.minecraft.client.gl.GlUniform -import net.minecraft.client.gl.VertexBuffer -import net.minecraft.client.render.Tessellator -import net.minecraft.client.render.VertexFormat -import net.minecraft.client.render.VertexFormats -import org.lwjgl.opengl.GL30 import java.io.Closeable -/** - * A GLSL shader renderer. Takes a vertex and fragment shader and renders it to the canvas. - * - * Inspired from the GLSL Panorama Shader Mod - * https://github.com/magistermaks/mod-glsl - */ -class Shader(vertex: String, fragment: String) : Closeable { - - private var buffer: VertexBuffer - private var canvas: ScalableCanvas - - private var program = 0 +open class Shader(vertex: String, fragment: String, private val uniforms: Array = emptyArray()) : + Closeable { - inner class UniformPointer(val name: String) { - val pointer = GlUniform.getUniformLocation(program, name) - } - - private val timeLocation: Int - private val mouseLocation: Int - private val resolutionLocation: Int - - private var time = 0f + var program = 0 init { val vertProgram = compileShader(vertex, GlConst.GL_VERTEX_SHADER) val fragProgram = compileShader(fragment, GlConst.GL_FRAGMENT_SHADER) - this.canvas = ScalableCanvas() - this.buffer = VertexBuffer(VertexBuffer.Usage.DYNAMIC) this.program = GlStateManager.glCreateProgram() GlStateManager.glAttachShader(program, vertProgram) @@ -62,26 +48,9 @@ class Shader(vertex: String, fragment: String) : Closeable { GlStateManager.glDeleteShader(vertProgram) GlStateManager.glDeleteShader(fragProgram) - // bake buffer data - val builder = Tessellator.getInstance() - val buffer = builder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR) - buffer.vertex(-1.0f, -1.0f, 1.0f).texture(0f, 0f) - .color(1f, 1f, 1f, 1f) - buffer.vertex(1.0f, -1.0f, 1.0f).texture(1f, 0f) - .color(1f, 1f, 1f, 1f) - buffer.vertex(1.0f, 1.0f, 1.0f).texture(1f, 1f) - .color(1f, 1f, 1f, 1f) - buffer.vertex(-1.0f, 1.0f, 1.0f).texture(0f, 1f) - .color(1f, 1f, 1f, 1f) - - this.buffer.bind() - this.buffer.upload(buffer.end()) - VertexBuffer.unbind() - - // get uniform pointers - timeLocation = GlUniform.getUniformLocation(program, "time") - mouseLocation = GlUniform.getUniformLocation(program, "mouse") - resolutionLocation = GlUniform.getUniformLocation(program, "resolution") + uniforms.forEach { uniform -> + uniform.init(program) + } } private fun compileShader(source: String, type: Int): Int { @@ -98,28 +67,19 @@ class Shader(vertex: String, fragment: String) : Closeable { return shader } - fun draw(mouseX: Int, mouseY: Int, delta: Float) { + fun use() { GlProgramManager.useProgram(this.program) + uniforms.forEach { uniform -> + uniform.set(uniform.pointer) + } + } - canvas.resize(mc.window.framebufferWidth, mc.window.framebufferHeight) - canvas.write() - - // update uniforms - GL30.glUniform1f(timeLocation, time) - time += (delta / 10f) - GL30.glUniform2f(mouseLocation, mouseX.toFloat(), mouseY.toFloat()) - GL30.glUniform2f(resolutionLocation, canvas.width().toFloat(), canvas.height().toFloat()) - - // draw - buffer.bind() - buffer.draw() - canvas.blit(buffer) + fun stop() { + GlProgramManager.useProgram(0) } override fun close() { GlStateManager.glDeleteProgram(this.program) - buffer.close() - canvas.close() } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/UniformProvider.kt b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/UniformProvider.kt new file mode 100644 index 00000000000..3fe956d049a --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/UniformProvider.kt @@ -0,0 +1,31 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.render.shader + +import net.minecraft.client.gl.GlUniform + +class UniformProvider(val name: String, val set: (pointer: Int) -> Unit) { + + var pointer = -1 + + fun init(program: Int) { + pointer = GlUniform.getUniformLocation(program, name) + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/shaders/OutlineEffectShader.kt b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/shaders/OutlineEffectShader.kt new file mode 100644 index 00000000000..4ab5800f7d0 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/render/shader/shaders/OutlineEffectShader.kt @@ -0,0 +1,40 @@ +package net.ccbluex.liquidbounce.render.shader.shaders + +import net.ccbluex.liquidbounce.render.engine.Color4b +import net.ccbluex.liquidbounce.render.shader.FramebufferShader +import net.ccbluex.liquidbounce.render.shader.Shader +import net.ccbluex.liquidbounce.render.shader.UniformProvider +import net.ccbluex.liquidbounce.utils.io.resourceToString +import org.lwjgl.opengl.GL20 + +object OutlineEffectShaderData { + var blendColor = Color4b.WHITE + var sampleMul = 1f + var glowColor = Color4b.BLUE + var falloff = 1f + var layerCount = 2 + var alpha = 1f +} + +object OutlineEffectShader : FramebufferShader( + Shader( + resourceToString("/assets/liquidbounce/shaders/glow/plane_projection.vert"), + resourceToString("/assets/liquidbounce/shaders/glow/glow.frag"), + arrayOf( + UniformProvider("texture0") { pointer -> GL20.glUniform1i(pointer, 0) }, + UniformProvider("image") { pointer -> GL20.glUniform1i(pointer, 0) }, + UniformProvider("useImage") { pointer -> GL20.glUniform1i(pointer, 0) }, + UniformProvider("blendColor") { pointer -> OutlineEffectShaderData.blendColor.putToUniform(pointer) }, + UniformProvider("alpha") { pointer -> GL20.glUniform1f(pointer, OutlineEffectShaderData.alpha) }, + UniformProvider("sampleMul") { pointer -> + GL20.glUniform1f(pointer, OutlineEffectShaderData.sampleMul) + }, + + UniformProvider("glowColor") { pointer -> OutlineEffectShaderData.glowColor.putToUniform(pointer) }, + UniformProvider("falloff") { pointer -> GL20.glUniform1f(pointer, OutlineEffectShaderData.falloff) }, + UniformProvider("layerCount") { pointer -> + GL20.glUniform1i(pointer, OutlineEffectShaderData.layerCount) + } + ) + ) +) diff --git a/src/main/resources/assets/liquidbounce/lang/en_us.json b/src/main/resources/assets/liquidbounce/lang/en_us.json index 6ccde95780c..ac231beef0e 100644 --- a/src/main/resources/assets/liquidbounce/lang/en_us.json +++ b/src/main/resources/assets/liquidbounce/lang/en_us.json @@ -616,5 +616,6 @@ "liquidbounce.module.dupe.description": "Attempts to Auto-Dupe items from your inventory by using exploits.", "liquidbounce.module.surround.description": "Builds holes that protect you from explosion damage.", "liquidbounce.module.packetMine.description": "Allows you to mine blocks by clicking them once.", - "liquidbounce.module.fastExp.description": "Automatically repairs your armor." + "liquidbounce.module.fastExp.description": "Automatically repairs your armor.", + "liquidbounce.module.itemChams.description": "Applies visual effects to your held items." } diff --git a/src/main/resources/assets/liquidbounce/shaders/glow/glow.frag b/src/main/resources/assets/liquidbounce/shaders/glow/glow.frag new file mode 100644 index 00000000000..dc352b32a9b --- /dev/null +++ b/src/main/resources/assets/liquidbounce/shaders/glow/glow.frag @@ -0,0 +1,78 @@ +/** + * Author: ccetl + * Created: 2024 + * License: GPL-3.0 + */ +#version 410 core + +in vec2 fragTexCoord; +out vec4 fragColor; + +uniform sampler2D texture0; + +uniform sampler2D image; +uniform int useImage; + +uniform float alpha; +uniform vec4 blendColor; + +uniform float sampleMul; +uniform vec4 glowColor; +uniform float falloff; +uniform int layerCount; + +vec4 getFinalColor(vec4 color) { + if (blendColor.a == 0.0) { + return vec4(color.rgb, alpha); + } + + return vec4((color.rgb * vec3(1.0 - blendColor.a)) + (blendColor.rgb * vec3(blendColor.a)), alpha); +} + +void main() { + vec2 uv = fragTexCoord.xy; + vec2 pos = gl_FragCoord.xy; + + vec4 color = textureLod(texture0, uv, 0.0); + if (color.a != 0.0) { + if (useImage == 1) { + fragColor = getFinalColor(textureLod(image, uv, 0.0)); + return; + } + + fragColor = getFinalColor(color); + return; + } + + if (glowColor.a == 0.0) { + discard; + } + + vec2 texelSize = vec2(1.0) / textureSize(texture0, 0).xy; + float alpha = 0.0; + + for (int ix = -layerCount; ix <= layerCount; ix++) { + for (int iy = -layerCount; iy <= layerCount; iy++) { + if (ix == 0 && iy == 0) { + continue; + } + + float x = sampleMul * float(ix); + float y = sampleMul * float(iy); + + float distance = length(vec2(x, y)); + float weight = max(0.0, 1.0 - (distance / falloff)); + vec2 offset = vec2(texelSize.x * x, texelSize.y * y); + float positionAlpha = textureLod(texture0, uv + offset, 0.0).a; + + alpha += positionAlpha * weight; + } + } + + if (alpha == 0.0) { + discard; + } + + vec4 outColor = vec4(glowColor.rgb, alpha * glowColor.a); + fragColor = outColor; +} diff --git a/src/main/resources/assets/liquidbounce/shaders/glow/plane_projection.vert b/src/main/resources/assets/liquidbounce/shaders/glow/plane_projection.vert new file mode 100644 index 00000000000..40fef2278bc --- /dev/null +++ b/src/main/resources/assets/liquidbounce/shaders/glow/plane_projection.vert @@ -0,0 +1,11 @@ +#version 410 core + +in vec3 Position; +in vec2 UV0; + +out vec2 fragTexCoord; + +void main() { + gl_Position = vec4((vec4(Position.xy, 0.0, 1.0)).xy, 0.2, 1.0); + fragTexCoord = UV0; +}