diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 63280e8f4..163a132d2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; import com.seibel.distanthorizons.core.render.glObject.buffer.QuadElementBuffer; -import com.seibel.distanthorizons.core.render.renderer.shaders.SSAORenderer; +import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; @@ -244,7 +244,7 @@ public class LodRenderer bufferHandler.renderOpaque(this); if (Config.Client.Advanced.Graphics.Quality.ssao.get()) { - SSAORenderer.INSTANCE.render(partialTicks); + SSAOShader.INSTANCE.render(partialTicks); } //======================// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java new file mode 100644 index 000000000..623841f3e --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java @@ -0,0 +1,152 @@ +package com.seibel.distanthorizons.core.render.renderer.shaders; + +import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.render.glObject.GLState; +import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL32; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public abstract class AbstractShaderRenderer { + protected static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + private static final float[] box_vertices = { + -1, -1, + 1, -1, + 1, 1, + -1, -1, + 1, 1, + -1, 1, + }; + + protected final ShaderProgram shader; + protected final ShaderProgram applyShader; + protected GLVertexBuffer boxBuffer; + protected VertexAttribute va; + boolean init = false; + + private int width = -1; + private int height = -1; + private int framebuffer = -1; + private int shaderTexture = -1; + + + protected AbstractShaderRenderer(ShaderProgram shader) { + this(shader, null); + } + + protected AbstractShaderRenderer(ShaderProgram shader, ShaderProgram applyShader) { + this.shader = shader; + this.applyShader = applyShader; + + + } + private void init() { + if (init) return; + init = true; + + va = VertexAttribute.create(); + va.bind(); + // Pos + va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + va.completeAndCheck(Float.BYTES * 2); + + // Some shader stuff needs to be set a bit later than + this.postInit(); + // Framebuffer + createBuffer(); + } + + /** Overwrite this to apply uniforms to the shader */ + void setShaderUniforms(float partialTicks) {}; + /** Overwrite this to apply uniforms to the apply shader */ + void setApplyShaderUniforms(float partialTicks) {}; + /** Overwrite if you need to run something on runtime */ + void postInit() {}; + + public void render(float partialTicks) { + GLState state = new GLState(); + init(); + int width = MC_RENDER.getTargetFrameBufferViewportWidth(); + int height = MC_RENDER.getTargetFrameBufferViewportHeight(); + + if (this.width != width || this.height != height) { + this.width = width; + this.height = height; + createFramebuffer(width, height); + } + + + + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, framebuffer); + GL32.glViewport(0, 0, width, height); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_BLEND); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + + + shader.bind(); + this.setShaderUniforms(partialTicks); + va.bind(); + va.bindBufferToAllBindingPoint(boxBuffer.getId()); + + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + + GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); + + if (applyShader != null) { + applyShader.bind(); + this.setApplyShaderUniforms(partialTicks); + } + GL32.glEnable(GL11.GL_BLEND); + GL32.glBlendFunc(GL32.GL_ZERO, GL32.GL_SRC_ALPHA); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture); + GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); + + + + state.restore(); + } + + + private void createFramebuffer(int width, int height) { + if (framebuffer != -1) { + GL32.glDeleteFramebuffers(framebuffer); + framebuffer = -1; + } + + if (shaderTexture != -1) { + GL32.glDeleteTextures(shaderTexture); + shaderTexture = -1; + } + + framebuffer = GL32.glGenFramebuffers(); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, framebuffer); + + shaderTexture = GL32.glGenTextures(); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture); + GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, shaderTexture, 0); + } + + private void createBuffer() { + ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); + buffer.order(ByteOrder.nativeOrder()); + buffer.asFloatBuffer().put(box_vertices); + buffer.rewind(); + boxBuffer = new GLVertexBuffer(false); + boxBuffer.bind(); + boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); + } +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java deleted file mode 100644 index faa648fcb..000000000 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.seibel.distanthorizons.core.render.renderer.shaders; - -import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; -import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.render.glObject.GLState; -import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; -import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; -import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute; -import com.seibel.distanthorizons.core.util.LodUtil; -import com.seibel.distanthorizons.core.util.RenderUtil; -import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL32; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -public class SSAORenderer { - public static SSAORenderer INSTANCE = new SSAORenderer(); - - public SSAORenderer() { - } - - private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - - private static final float[] box_vertices = { - -1, -1, - 1, -1, - 1, 1, - -1, -1, - 1, 1, - -1, 1, - }; - - ShaderProgram ssaoShader; - ShaderProgram applyShader; - GLVertexBuffer boxBuffer; - VertexAttribute va; - boolean init = false; - - private static final int MAX_KERNEL_SIZE = 32; - private float[] kernel = new float[MAX_KERNEL_SIZE * 3]; - - public void init() { - if (init) return; - - init = true; - va = VertexAttribute.create(); - va.bind(); - // Pos - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - va.completeAndCheck(Float.BYTES * 2); - ssaoShader = new ShaderProgram("shaders/ssao/ao-vert.vert", "shaders/ssao/ao-frag.frag", - "fragColor", new String[]{"vPosition"}); - - applyShader = new ShaderProgram("shaders/ssao/ao-vert.vert", "shaders/ssao/apply-frag.frag", - "fragColor", new String[]{"vPosition"}); - - - // Generate kernel - kernel = genKernel(); - // Framebuffer - createBuffer(); - } - - private int width = -1; - private int height = -1; - private int ssaoFramebuffer = -1; - - private int ssaoTexture = -1; - - private void createFramebuffer(int width, int height) { - if (ssaoFramebuffer != -1) { - GL32.glDeleteFramebuffers(ssaoFramebuffer); - ssaoFramebuffer = -1; - } - - if (ssaoTexture != -1) { - GL32.glDeleteTextures(ssaoTexture); - ssaoTexture = -1; - } - - ssaoFramebuffer = GL32.glGenFramebuffers(); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer); - - ssaoTexture = GL32.glGenTextures(); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture); - GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, ssaoTexture, 0); - } - - private void createBuffer() { - ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(box_vertices); - buffer.rewind(); - boxBuffer = new GLVertexBuffer(false); - boxBuffer.bind(); - boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); - } - - private static float[] genKernel() { - float[] kernel = new float[MAX_KERNEL_SIZE * 3]; - for (int i = 0; i < MAX_KERNEL_SIZE; i++) { - float sampleX = (float) (Math.random() * 2.0 - 1.0); - float sampleY = (float) (Math.random() * 2.0 - 1.0); - float sampleZ = (float) Math.random(); - - - // Normalize - float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2)); - sampleX /= magnitude; - sampleY /= magnitude; - sampleZ /= magnitude; - - float scale = i / (float) MAX_KERNEL_SIZE; - float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9)); - - sampleX *= interpolatedScale; - sampleY *= interpolatedScale; - sampleZ *= interpolatedScale; - kernel[i * 3] = sampleX; - kernel[i * 3 + 1] = sampleY; - kernel[i * 3 + 2] = sampleZ; - } - return kernel; - } - - public void render(float partialTicks) { - GLState state = new GLState(); - init(); - //GL32.glDepthMask(false); - int width = MC_RENDER.getTargetFrameBufferViewportWidth(); - int height = MC_RENDER.getTargetFrameBufferViewportHeight(); - - if (this.width != width || this.height != height) { - this.width = width; - this.height = height; - createFramebuffer(width, height); - } - - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer); - GL32.glViewport(0, 0, width, height); - GL32.glDisable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL32.GL_BLEND); - GL32.glDisable(GL32.GL_SCISSOR_TEST); - - - Mat4f perspective = Mat4f.perspective( - (float) MC_RENDER.getFov(partialTicks), - MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(), - RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks), - (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2))); - - ssaoShader.bind(); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gProj"), perspective); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gSampleRad"), 3.0f); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gFactor"), 0.8f); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gPower"), 1.0f); - va.bind(); - va.bindBufferToAllBindingPoint(boxBuffer.getId()); - - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - - GL32.glUniform3fv(ssaoShader.getUniformLocation("gKernel"), kernel); - GL32.glUniform1i(ssaoShader.getUniformLocation("gDepthMap"), 0); - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - - applyShader.bind(); - GL32.glEnable(GL11.GL_BLEND); - GL32.glBlendFunc(GL32.GL_ZERO, GL32.GL_SRC_ALPHA); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture); - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - - //GL32.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, ssaoFramebuffer); - //GL32.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); - //GL32.glBlitFramebuffer( - // 0, 0, width, height, - // 0, 0, width, height, - // GL11.GL_COLOR_BUFFER_BIT, - // GL11.GL_NEAREST - //); - - state.restore(); - } - - -} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java new file mode 100644 index 000000000..4c3495ee4 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java @@ -0,0 +1,75 @@ +package com.seibel.distanthorizons.core.render.renderer.shaders; + +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.util.RenderUtil; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import org.lwjgl.opengl.GL32; + +public class SSAOShader extends AbstractShaderRenderer { + public static SSAOShader INSTANCE = new SSAOShader(); + + private static final int MAX_KERNEL_SIZE = 32; + private float[] kernel = new float[MAX_KERNEL_SIZE * 3]; + + + public SSAOShader() { + super( + new ShaderProgram("shaders/ssao/ao.vert", "shaders/ssao/ao.frag", + "fragColor", new String[]{"vPos"}), + new ShaderProgram("shaders/ssao/ao.vert", "shaders/ssao/apply-frag.frag", + "fragColor", new String[]{"vPos"}) + ); + + } + @Override + void postInit() { + // Generate kernel + kernel = genKernel(); + } + + @Override + void setShaderUniforms(float partialTicks) { + Mat4f perspective = Mat4f.perspective( + (float) MC_RENDER.getFov(partialTicks), + MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(), + RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks), + (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2))); + + + this.shader.setUniform(this.shader.getUniformLocation("gProj"), perspective); + this.shader.setUniform(this.shader.getUniformLocation("gSampleRad"), 3.0f); + this.shader.setUniform(this.shader.getUniformLocation("gFactor"), 0.8f); + this.shader.setUniform(this.shader.getUniformLocation("gPower"), 1.0f); + + GL32.glUniform3fv(this.shader.getUniformLocation("gKernel"), kernel); + GL32.glUniform1i(this.shader.getUniformLocation("gDepthMap"), 0); + } + + private static float[] genKernel() { + float[] kernel = new float[MAX_KERNEL_SIZE * 3]; + for (int i = 0; i < MAX_KERNEL_SIZE; i++) { + float sampleX = (float) (Math.random() * 2.0 - 1.0); + float sampleY = (float) (Math.random() * 2.0 - 1.0); + float sampleZ = (float) Math.random(); + + + // Normalize + float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2)); + sampleX /= magnitude; + sampleY /= magnitude; + sampleZ /= magnitude; + + float scale = i / (float) MAX_KERNEL_SIZE; + float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9)); + + sampleX *= interpolatedScale; + sampleY *= interpolatedScale; + sampleZ *= interpolatedScale; + kernel[i * 3] = sampleX; + kernel[i * 3 + 1] = sampleY; + kernel[i * 3 + 2] = sampleZ; + } + return kernel; + } +} diff --git a/core/src/main/resources/shaders/noise/noise.frag b/core/src/main/resources/shaders/noise/noise.frag index 8ac1e1e99..d64f051dc 100644 --- a/core/src/main/resources/shaders/noise/noise.frag +++ b/core/src/main/resources/shaders/noise/noise.frag @@ -5,9 +5,8 @@ in vec4 vPos; in vec3 vertexWorldPos; out vec4 fragColor; -uniform float fogScale; +uniform float distanceScale; -uniform bool noiseEnabled; uniform int noiseSteps; uniform float noiseIntensity; uniform float noiseDropoff; @@ -67,25 +66,26 @@ void main() { // Modifies the color // A value of 0 on the randomValue will result in the original color, while a value of 1 will result in a fully bright color - vec3 newCol = vertexColor.rgb + (vec3(1.0) - vertexColor.rgb) * randomValue; + vec3 newCol = (vec3(1.0) - vertexColor.rgb) * randomValue; // Clamps it and turns it back into a vec4 - fragColor = mix( - vec4( - clamp(newCol.r, 0., 1.), - clamp(newCol.g, 0., 1.), - clamp(newCol.b, 0., 1.), - vertexColor.w - ), vertexColor, - clamp(length(vertexWorldPos) * fogScale * noiseDropoff, 0., 1.) // The further away it gets, the less noise gets applied + fragColor = vec4( + clamp(newCol.r, 0., 1.), + clamp(newCol.g, 0., 1.), + clamp(newCol.b, 0., 1.), + clamp(length(vertexWorldPos) * distanceScale * noiseDropoff, 0., 1.) // The further away it gets, the less noise gets applied + ); + fragColor = vec4( + 0f, 0f, 0f, + randomValue // The further away it gets, the less noise gets applied ); // For testing -// if (vertexColor.r != 69420.) { -// fragColor = vec4( -// mod(fixedVPos.x, 1), -// mod(fixedVPos.y, 1), -// mod(fixedVPos.z, 1), -// vertexColor.w); -// } + if (vertexColor.r != 69420.) { + fragColor = vec4( + mod(fixedVPos.x, 1), + mod(fixedVPos.y, 1), + mod(fixedVPos.z, 1), + 1f); + } } \ No newline at end of file diff --git a/core/src/main/resources/shaders/ssao/ao-vert.vert b/core/src/main/resources/shaders/ssao/ao-vert.vert deleted file mode 100644 index a2e967ae0..000000000 --- a/core/src/main/resources/shaders/ssao/ao-vert.vert +++ /dev/null @@ -1,10 +0,0 @@ -#version 150 core - -in vec2 vPosition; -out vec2 TexCoord; - -void main() -{ - gl_Position = vec4(vPosition, 1.0, 1.0); - TexCoord = vPosition.xy * 0.5 + 0.5; -} \ No newline at end of file diff --git a/core/src/main/resources/shaders/ssao/ao-frag.frag b/core/src/main/resources/shaders/ssao/ao.frag similarity index 100% rename from core/src/main/resources/shaders/ssao/ao-frag.frag rename to core/src/main/resources/shaders/ssao/ao.frag diff --git a/core/src/main/resources/shaders/ssao/ao.vert b/core/src/main/resources/shaders/ssao/ao.vert new file mode 100644 index 000000000..b65ef2cff --- /dev/null +++ b/core/src/main/resources/shaders/ssao/ao.vert @@ -0,0 +1,15 @@ +#version 150 core + +in vec2 vPos; +out vec2 TexCoord; + +out vec4 vertexColor; +out vec3 vertexWorldPos; +out float vertexYPos; + + +void main() +{ + gl_Position = vec4(vPos, 1.0, 1.0); + TexCoord = vPos.xy * 0.5 + 0.5; +} \ No newline at end of file