diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java index 74f79c21a..da4d5c7fe 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java @@ -19,34 +19,32 @@ package com.seibel.distanthorizons.core.render.glObject; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.seibel.distanthorizons.api.enums.config.EGLErrorHandlingMode; +import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.enums.EGLProxyContext; +import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.objects.GLMessage; +import com.seibel.distanthorizons.core.util.objects.GLMessageOutputStream; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; +import com.seibel.distanthorizons.coreapi.ModInfo; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GL32; +import org.lwjgl.opengl.GLCapabilities; +import org.lwjgl.opengl.GLUtil; + import java.io.PrintStream; import java.lang.invoke.MethodHandles; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import com.seibel.distanthorizons.api.enums.config.EGLErrorHandlingMode; -import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; -import com.seibel.distanthorizons.core.config.Config; -import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.lwjgl.glfw.GLFW; -import org.lwjgl.opengl.GL; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL32; -import org.lwjgl.opengl.GLCapabilities; -import org.lwjgl.opengl.GLUtil; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.seibel.distanthorizons.coreapi.ModInfo; -import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; -import com.seibel.distanthorizons.core.enums.EGLProxyContext; -import com.seibel.distanthorizons.core.util.objects.GLMessage; -import com.seibel.distanthorizons.core.util.objects.GLMessageOutputStream; -import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; - /** * A singleton that holds references to different openGL contexts * and GPU capabilities. @@ -108,7 +106,7 @@ public class GLProxy // this must be created on minecraft's render context to work correctly GL_LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error."); - GL_LOGGER.info("Lod Render OpenGL version [" + GL11.glGetString(GL11.GL_VERSION) + "]."); + GL_LOGGER.info("Lod Render OpenGL version [" + GL32.glGetString(GL32.GL_VERSION) + "]."); // getting Minecraft's context has to be done on the render thread, // where the GL context is 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 dee4ede60..2d9609681 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 @@ -243,16 +243,23 @@ public class LodRenderer { this.shaderProgram.free(); this.shaderProgram = new LodRenderProgram(newFogConfig); + FogShader.INSTANCE.free(); FogShader.INSTANCE = new FogShader(newFogConfig); } this.shaderProgram.bind(); } + GL32.glActiveTexture(GL32.GL_TEXTURE0); /*---------Get required data--------*/ int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; - Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks); + //Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks); + + Mat4f projectionMatrix = RenderUtil.createLodProjectionMatrix(baseProjectionMatrix, partialTicks); + + Mat4f modelViewProjectionMatrix = new Mat4f(projectionMatrix); + modelViewProjectionMatrix.multiply(RenderUtil.createLodModelViewMatrix(baseModelViewMatrix)); /*---------Fill uniform data--------*/ this.shaderProgram.fillUniformData(modelViewProjectionMatrix, /*Light map = GL_TEXTURE0*/ 0, @@ -283,12 +290,12 @@ public class LodRenderer if (Config.Client.Advanced.Graphics.Ssao.enabled.get()) { profiler.popPush("LOD SSAO"); + SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix); SSAORenderer.INSTANCE.render(minecraftGlState, partialTicks); } profiler.popPush("LOD Fog"); - // TODO add the model view/projection matrices to the render() function FogShader.INSTANCE.setModelViewProjectionMatrix(modelViewProjectionMatrix); FogShader.INSTANCE.render(partialTicks); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java new file mode 100644 index 000000000..9a52a753a --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java @@ -0,0 +1,125 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer; + +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.render.glObject.GLState; +import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOApplyShader; +import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import org.lwjgl.opengl.GL32; + +import java.nio.ByteBuffer; + +public class SSAORenderer +{ + public static SSAORenderer INSTANCE = new SSAORenderer(); + + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + + private boolean init = false; + + private int width = -1; + private int height = -1; + private int ssaoFramebuffer = -1; + + private int ssaoTexture = -1; + + + //=============// + // constructor // + //=============// + + private SSAORenderer() { } + + public void init() + { + if (this.init) return; + this.init = true; + + SSAOShader.INSTANCE.init(); + + SSAOApplyShader.INSTANCE.init(); + } + + private void createFramebuffer(int width, int height) + { + if (this.ssaoFramebuffer != -1) + { + GL32.glDeleteFramebuffers(this.ssaoFramebuffer); + this.ssaoFramebuffer = -1; + } + + if (this.ssaoTexture != -1) + { + GL32.glDeleteTextures(this.ssaoTexture); + this.ssaoTexture = -1; + } + + this.ssaoFramebuffer = GL32.glGenFramebuffers(); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer); + + this.ssaoTexture = GL32.glGenTextures(); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture); + GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R16F, width, height, 0, GL32.GL_RED, GL32.GL_HALF_FLOAT, (ByteBuffer) null); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR); + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.ssaoTexture, 0); + } + + + //========// + // render // + //========// + + public void render(GLState primaryState, float partialTicks) + { + GLState state = new GLState(); + + this.init(); + + int width = MC_RENDER.getTargetFrameBufferViewportWidth(); + int height = MC_RENDER.getTargetFrameBufferViewportHeight(); + + if (this.width != width || this.height != height) + { + this.width = width; + this.height = height; + this.createFramebuffer(width, height); + } + + SSAOShader.INSTANCE.FrameBuffer = this.ssaoFramebuffer; + SSAOShader.INSTANCE.render(partialTicks); + + primaryState.RestoreFrameBuffer(); + + SSAOApplyShader.INSTANCE.BufferTexture = this.ssaoTexture; + SSAOApplyShader.INSTANCE.render(partialTicks); + + state.restore(); + } + + public void free() + { + SSAOShader.INSTANCE.free(); + SSAOApplyShader.INSTANCE.free(); + } +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/ScreenQuad.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/ScreenQuad.java new file mode 100644 index 000000000..aa3014b1b --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/ScreenQuad.java @@ -0,0 +1,91 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer; + +import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; +import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute; +import org.lwjgl.opengl.GL32; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class ScreenQuad +{ + public static ScreenQuad INSTANCE = new ScreenQuad(); + + private static final float[] box_vertices = { + -1, -1, + 1, -1, + 1, 1, + -1, -1, + 1, 1, + -1, 1, + }; + + private GLVertexBuffer boxBuffer; + private VertexAttribute va; + private boolean init = false; + + + //=============// + // constructor // + //=============// + + private ScreenQuad() { } + + public void init() + { + if (this.init) return; + this.init = true; + + this.va = VertexAttribute.create(); + this.va.bind(); + + // Pos + this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + this.va.completeAndCheck(Float.BYTES * 2); + + // Framebuffer + this.createBuffer(); + } + + public void render() + { + this.init(); + + this.va.bind(); + this.va.bindBufferToAllBindingPoint(this.boxBuffer.getId()); + + GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); + } + + private void createBuffer() + { + ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); + buffer.order(ByteOrder.nativeOrder()); + buffer.asFloatBuffer().put(box_vertices); + buffer.rewind(); + + this.boxBuffer = new GLVertexBuffer(false); + this.boxBuffer.bind(); + this.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/AbstractShaderRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java index 9dc1006a5..c098da287 100644 --- 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 @@ -19,120 +19,56 @@ 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.IMinecraftClientWrapper; 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 IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); 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; - public GLVertexBuffer boxBuffer; - protected VertexAttribute va; - boolean init = false; + protected ShaderProgram shader; + + protected boolean init = false; - protected AbstractShaderRenderer(ShaderProgram shader) + protected AbstractShaderRenderer() {} + + public void init() { - this.shader = shader; + if (this.init) return; + this.init = true; + + this.onInit(); } - private void init() - { - if (init) return; - init = true; - - va = VertexAttribute.create(); - va.bind(); - - // Pos - setVertexAttributes(); - va.completeAndCheck(Float.BYTES * 2); - - // Some shader stuff needs to be set a bit later than - this.postInit(); - - // Framebuffer - this.createBuffer(); - } - - /** Sets all the vertex attributes */ - void setVertexAttributes() - { - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - } - - /** Overwrite this to apply uniforms to the shader */ - void setShaderUniforms(float partialTicks) { } - - /** Overwrite if you need to run something on runtime */ - void postInit() { } - - - // TODO pass in the Model View and Projection Matrices along with the ticks public void render(float partialTicks) { - GLState state = new GLState(); this.init(); + this.shader.bind(); + + this.onApplyUniforms(partialTicks); + int width = MC_RENDER.getTargetFrameBufferViewportWidth(); int height = MC_RENDER.getTargetFrameBufferViewportHeight(); - GL32.glViewport(0, 0, width, height); - GL32.glDisable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL32.GL_SCISSOR_TEST); - shader.bind(); - this.setShaderUniforms(partialTicks); + this.onRender(); - va.bind(); - va.bindBufferToAllBindingPoint(boxBuffer.getId()); - - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - - GL32.glEnable(GL11.GL_BLEND); - GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - - state.restore(); - } - - private void createBuffer() - { - ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(box_vertices); - buffer.rewind(); - - this.boxBuffer = new GLVertexBuffer(false); - this.boxBuffer.bind(); - this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); + this.shader.unbind(); } public void free() { this.shader.free(); } + + protected void onInit() {} + + protected void onApplyUniforms(float partialTicks) {} + + protected void onRender() {} } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java index b0eab9b78..0e9341faa 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java @@ -19,15 +19,45 @@ package com.seibel.distanthorizons.core.render.renderer.shaders; +import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; +import org.lwjgl.opengl.GL32; public class DarkShader extends AbstractShaderRenderer { public static DarkShader INSTANCE = new DarkShader(); + - protected DarkShader() + @Override + public void onInit() { - super(new ShaderProgram("shaders/normal.vert", "shaders/test/dark.frag", "fragColor", new String[]{"vPosition", "color"})); + this.shader = new ShaderProgram( + "shaders/normal.vert", + "shaders/test/dark.frag", + "fragColor", + new String[]{"vPosition", "color"}); } + @Override + protected void onApplyUniforms(float partialTicks) + { + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + } + + @Override + protected void onRender() + { + GLState state = new GLState(); + + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); + + ScreenQuad.INSTANCE.render(); + + state.restore(); + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java index efbc1f368..d66b06eb8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java @@ -23,11 +23,14 @@ import com.seibel.distanthorizons.api.enums.rendering.EFogColorMode; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.render.fog.LodFogConfig; +import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.shader.Shader; import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import org.lwjgl.opengl.GL32; @@ -36,31 +39,40 @@ import java.awt.*; public class FogShader extends AbstractShaderRenderer { public static FogShader INSTANCE = new FogShader(LodFogConfig.generateFogConfig()); + + private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class); - public final int gInvertedModelViewProjectionUniform; - public final int gDepthMapUniform; + private final LodFogConfig fogConfig; + private Mat4f inverseMvmProjMatrix; + public int gInvertedModelViewProjectionUniform; + public int gDepthMapUniform; // Fog Uniforms - public final int fogColorUniform; - public final int fogScaleUniform; - public final int fogVerticalScaleUniform; - public final int nearFogStartUniform; - public final int nearFogLengthUniform; - public final int fullFogModeUniform; - + public int fogColorUniform; + public int fogScaleUniform; + public int fogVerticalScaleUniform; + public int nearFogStartUniform; + public int nearFogLengthUniform; + public int fullFogModeUniform; public FogShader(LodFogConfig fogConfig) { - super(new ShaderProgram( + this.fogConfig = fogConfig; + } + + @Override + public void onInit() + { + this.shader = new ShaderProgram( // TODO rename normal.vert to something like "postProcess.vert" () -> Shader.loadFile("shaders/normal.vert", false, new StringBuilder()).toString(), - () -> fogConfig.loadAndProcessFragShader("shaders/fog/fog.frag", false).toString(), + () -> this.fogConfig.loadAndProcessFragShader("shaders/fog/fog.frag", false).toString(), "fragColor", new String[]{"vPosition"} - )); - + ); + // all uniforms should be tryGet... // because disabling fog can cause the GLSL to optimize out most (if not all) uniforms @@ -79,9 +91,9 @@ public class FogShader extends AbstractShaderRenderer } @Override - void setShaderUniforms(float partialTicks) + protected void onApplyUniforms(float partialTicks) { - this.shader.bind(); + this.shader.setUniform(this.gInvertedModelViewProjectionUniform, this.inverseMvmProjMatrix); int lodDrawDistance = RenderUtil.getFarClipPlaneDistanceInBlocks(); int vanillaDrawDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; @@ -127,12 +139,25 @@ public class FogShader extends AbstractShaderRenderer public void setModelViewProjectionMatrix(Mat4f combinedModelViewProjectionMatrix) { - this.shader.bind(); + this.inverseMvmProjMatrix = new Mat4f(combinedModelViewProjectionMatrix); + this.inverseMvmProjMatrix.invert(); + } + + @Override + protected void onRender() + { + GLState state = new GLState(); - Mat4f inverseMvmProjMatrix = new Mat4f(combinedModelViewProjectionMatrix); - inverseMvmProjMatrix.invert(); - this.shader.setUniform(this.gInvertedModelViewProjectionUniform, inverseMvmProjMatrix); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); - this.shader.unbind(); + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + + ScreenQuad.INSTANCE.render(); + + state.restore(); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java new file mode 100644 index 000000000..66d1dbfbe --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java @@ -0,0 +1,110 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer.shaders; + +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.util.RenderUtil; +import org.lwjgl.opengl.GL32; + +public class SSAOApplyShader extends AbstractShaderRenderer +{ + public static SSAOApplyShader INSTANCE = new SSAOApplyShader(); + + public int BufferTexture; + + // uniforms + public int gSSAOMapUniform; + public int gDepthMapUniform; + public int gViewSizeUniform; + public int gBlurRadiusUniform; + public int gNearUniform; + public int gFarUniform; + + + @Override + public void onInit() + { + this.shader = new ShaderProgram( + "shaders/normal.vert", + "shaders/ssao/apply.frag", + "fragColor", + new String[]{"vPosition"}); + + // uniform setup + this.gSSAOMapUniform = this.shader.getUniformLocation("gSSAOMap"); + this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap"); + this.gViewSizeUniform = this.shader.tryGetUniformLocation("gViewSize"); + this.gBlurRadiusUniform = this.shader.tryGetUniformLocation("gBlurRadius"); + this.gNearUniform = this.shader.tryGetUniformLocation("gNear"); + this.gFarUniform = this.shader.tryGetUniformLocation("gFar"); + } + + @Override + protected void onApplyUniforms(float partialTicks) + { + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + GL32.glUniform1i(this.gDepthMapUniform, 0); + + GL32.glActiveTexture(GL32.GL_TEXTURE1); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.BufferTexture); + GL32.glUniform1i(this.gSSAOMapUniform, 1); + + GL32.glUniform1i(this.gBlurRadiusUniform, + Config.Client.Advanced.Graphics.Ssao.blurRadius.get()); + + if (this.gViewSizeUniform >= 0) + { + GL32.glUniform2f(this.gViewSizeUniform, + MC_RENDER.getTargetFrameBufferViewportWidth(), + MC_RENDER.getTargetFrameBufferViewportHeight()); + } + + if (this.gNearUniform >= 0) + { + GL32.glUniform1f(this.gNearUniform, + RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks)); + } + + if (this.gFarUniform >= 0) + { + float far = (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2)); + GL32.glUniform1f(this.gFarUniform, far); + } + } + + + //========// + // render // + //========// + + @Override + protected void onRender() + { + GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendEquation(GL32.GL_FUNC_ADD); + GL32.glBlendFuncSeparate(GL32.GL_ZERO, GL32.GL_SRC_ALPHA, GL32.GL_ZERO, GL32.GL_ONE); + + ScreenQuad.INSTANCE.render(); + } +} 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 c7eec888a..000000000 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * This file is part of the Distant Horizons mod - * licensed under the GNU LGPL v3 License. - * - * Copyright (C) 2020-2023 James Seibel - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3. - * - * This program 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.seibel.distanthorizons.core.render.renderer.shaders; - -import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; -import com.seibel.distanthorizons.core.config.Config; -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(); - - 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, - }; - - - private ShaderProgram ssaoShader; - private ShaderProgram applyShader; - - private GLVertexBuffer boxBuffer; - private VertexAttribute va; - private boolean init = false; - - private int width = -1; - private int height = -1; - private int ssaoFramebuffer = -1; - - private int ssaoTexture = -1; - - // ssao uniforms - private final SsaoShaderUniforms ssaoShaderUniforms = new SsaoShaderUniforms(); - private static class SsaoShaderUniforms - { - public int gProjUniform; - public int gInvProjUniform; - public int gSampleCountUniform; - public int gRadiusUniform; - public int gStrengthUniform; - public int gMinLightUniform; - public int gBiasUniform; - public int gDepthMapUniform; - } - - // apply uniforms - private final ApplyShaderUniforms applyShaderUniforms = new ApplyShaderUniforms(); - private static class ApplyShaderUniforms - { - public int gSSAOMapUniform; - public int gDepthMapUniform; - public int gViewSizeUniform; - public int gBlurRadiusUniform; - public int gNearUniform; - public int gFarUniform; - } - - - //=============// - // constructor // - //=============// - - private SSAORenderer() { } - - public void init() - { - if (this.init) return; - this.init = true; - - this.va = VertexAttribute.create(); - this.va.bind(); - - // Pos - this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - this.va.completeAndCheck(Float.BYTES * 2); - this.ssaoShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag", - "fragColor", new String[]{"vPosition"}); - - this.applyShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply.frag", - "fragColor", new String[]{"vPosition"}); - - // SSAO uniform setup - this.ssaoShaderUniforms.gProjUniform = this.ssaoShader.getUniformLocation("gProj"); - this.ssaoShaderUniforms.gInvProjUniform = this.ssaoShader.getUniformLocation("gInvProj"); - this.ssaoShaderUniforms.gSampleCountUniform = this.ssaoShader.getUniformLocation("gSampleCount"); - this.ssaoShaderUniforms.gRadiusUniform = this.ssaoShader.getUniformLocation("gRadius"); - this.ssaoShaderUniforms.gStrengthUniform = this.ssaoShader.getUniformLocation("gStrength"); - this.ssaoShaderUniforms.gMinLightUniform = this.ssaoShader.getUniformLocation("gMinLight"); - this.ssaoShaderUniforms.gBiasUniform = this.ssaoShader.getUniformLocation("gBias"); - this.ssaoShaderUniforms.gDepthMapUniform = this.ssaoShader.getUniformLocation("gDepthMap"); - - // Apply uniform setup - this.applyShaderUniforms.gSSAOMapUniform = this.applyShader.getUniformLocation("gSSAOMap"); - this.applyShaderUniforms.gDepthMapUniform = this.applyShader.getUniformLocation("gDepthMap"); - this.applyShaderUniforms.gViewSizeUniform = this.applyShader.tryGetUniformLocation("gViewSize"); - this.applyShaderUniforms.gBlurRadiusUniform = this.applyShader.tryGetUniformLocation("gBlurRadius"); - this.applyShaderUniforms.gNearUniform = this.applyShader.tryGetUniformLocation("gNear"); - this.applyShaderUniforms.gFarUniform = this.applyShader.tryGetUniformLocation("gFar"); - - // Framebuffer - this.createBuffer(); - } - - private void createFramebuffer(int width, int height) - { - if (this.ssaoFramebuffer != -1) - { - GL32.glDeleteFramebuffers(this.ssaoFramebuffer); - this.ssaoFramebuffer = -1; - } - - if (this.ssaoTexture != -1) - { - GL32.glDeleteTextures(this.ssaoTexture); - this.ssaoTexture = -1; - } - - this.ssaoFramebuffer = GL32.glGenFramebuffers(); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer); - - this.ssaoTexture = GL32.glGenTextures(); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture); - GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R16F, width, height, 0, GL32.GL_RED, GL32.GL_HALF_FLOAT, (ByteBuffer) null); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR); - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.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(); - - this.boxBuffer = new GLVertexBuffer(false); - this.boxBuffer.bind(); - this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); - } - - - //========// - // render // - //========// - - public void render(GLState primaryState, float partialTicks) - { - GLState state = new GLState(); - - this.init(); - - int width = MC_RENDER.getTargetFrameBufferViewportWidth(); - int height = MC_RENDER.getTargetFrameBufferViewportHeight(); - - if (this.width != width || this.height != height) - { - this.width = width; - this.height = height; - this.createFramebuffer(width, height); - } - - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer); - GL32.glViewport(0, 0, width, height); - GL32.glDisable(GL32.GL_SCISSOR_TEST); - GL32.glDisable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL11.GL_BLEND); - - float near = RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks); - float far = (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2)); - - Mat4f perspective = Mat4f.perspective( - (float) MC_RENDER.getFov(partialTicks), - width / (float) height, - near, far); - - Mat4f invertedPerspective = new Mat4f(perspective); - invertedPerspective.invert(); - - int sampleCount = Config.Client.Advanced.Graphics.Ssao.sampleCount.get(); - int blurRadius = Config.Client.Advanced.Graphics.Ssao.blurRadius.get(); - float radius = Config.Client.Advanced.Graphics.Ssao.radius.get().floatValue(); - float strength = Config.Client.Advanced.Graphics.Ssao.strength.get().floatValue(); - float minLight = Config.Client.Advanced.Graphics.Ssao.minLight.get().floatValue(); - float bias = Config.Client.Advanced.Graphics.Ssao.bias.get().floatValue(); - - this.ssaoShader.bind(); - this.ssaoShader.setUniform(this.ssaoShaderUniforms.gProjUniform, perspective); - this.ssaoShader.setUniform(this.ssaoShaderUniforms.gInvProjUniform, invertedPerspective); - this.ssaoShader.setUniform(this.ssaoShaderUniforms.gSampleCountUniform, sampleCount); - this.ssaoShader.setUniform(this.ssaoShaderUniforms.gRadiusUniform, radius); - this.ssaoShader.setUniform(this.ssaoShaderUniforms.gStrengthUniform, strength); - this.ssaoShader.setUniform(this.ssaoShaderUniforms.gMinLightUniform, minLight); - this.ssaoShader.setUniform(this.ssaoShaderUniforms.gBiasUniform, bias); - - this.va.bind(); - this.va.bindBufferToAllBindingPoint(this.boxBuffer.getId()); - - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - - GL32.glUniform1i(this.ssaoShaderUniforms.gDepthMapUniform, 0); - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - - this.applyShader.bind(); - - primaryState.RestoreFrameBuffer(); - - GL32.glEnable(GL11.GL_BLEND); - GL32.glBlendEquation(GL32.GL_FUNC_ADD); - GL32.glBlendFuncSeparate(GL32.GL_ZERO, GL32.GL_SRC_ALPHA, GL32.GL_ZERO, GL32.GL_ONE); - - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - GL32.glUniform1i(this.applyShaderUniforms.gDepthMapUniform, 0); - - GL32.glActiveTexture(GL32.GL_TEXTURE1); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture); - GL32.glUniform1i(this.applyShaderUniforms.gSSAOMapUniform, 1); - - GL32.glUniform1i(this.applyShaderUniforms.gBlurRadiusUniform, blurRadius); - - if (this.applyShaderUniforms.gViewSizeUniform >= 0) - GL32.glUniform2f(this.applyShaderUniforms.gViewSizeUniform, width, height); - - if (this.applyShaderUniforms.gNearUniform >= 0) - GL32.glUniform1f(this.applyShaderUniforms.gNearUniform, near); - - if (this.applyShaderUniforms.gFarUniform >= 0) - GL32.glUniform1f(this.applyShaderUniforms.gFarUniform, far); - - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - - state.restore(); - } - - public void free() - { - this.ssaoShader.free(); - this.applyShader.free(); - } -} 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..34eee4b96 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java @@ -0,0 +1,116 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer.shaders; + +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import org.lwjgl.opengl.GL32; + +public class SSAOShader extends AbstractShaderRenderer +{ + public static SSAOShader INSTANCE = new SSAOShader(); + + public int FrameBuffer; + + private Mat4f perspective; + private Mat4f invertedPerspective; + + // uniforms + public int gProjUniform; + public int gInvProjUniform; + public int gSampleCountUniform; + public int gRadiusUniform; + public int gStrengthUniform; + public int gMinLightUniform; + public int gBiasUniform; + public int gDepthMapUniform; + + + @Override + public void onInit() + { + this.shader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag", + "fragColor", new String[]{"vPosition"}); + + // uniform setup + this.gProjUniform = this.shader.getUniformLocation("gProj"); + this.gInvProjUniform = this.shader.getUniformLocation("gInvProj"); + this.gSampleCountUniform = this.shader.getUniformLocation("gSampleCount"); + this.gRadiusUniform = this.shader.getUniformLocation("gRadius"); + this.gStrengthUniform = this.shader.getUniformLocation("gStrength"); + this.gMinLightUniform = this.shader.getUniformLocation("gMinLight"); + this.gBiasUniform = this.shader.getUniformLocation("gBias"); + this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap"); + } + + public void setProjectionMatrix(Mat4f perspective) + { + this.perspective = perspective; + + this.invertedPerspective = new Mat4f(perspective); + this.invertedPerspective.invert(); + } + + @Override + protected void onApplyUniforms(float partialTicks) + { + this.shader.setUniform(this.gProjUniform, this.perspective); + + this.shader.setUniform(this.gInvProjUniform, this.invertedPerspective); + + this.shader.setUniform(this.gSampleCountUniform, + Config.Client.Advanced.Graphics.Ssao.sampleCount.get()); + + this.shader.setUniform(this.gRadiusUniform, + Config.Client.Advanced.Graphics.Ssao.radius.get().floatValue()); + + this.shader.setUniform(this.gStrengthUniform, + Config.Client.Advanced.Graphics.Ssao.strength.get().floatValue()); + + this.shader.setUniform(this.gMinLightUniform, + Config.Client.Advanced.Graphics.Ssao.minLight.get().floatValue()); + + this.shader.setUniform(this.gBiasUniform, + Config.Client.Advanced.Graphics.Ssao.bias.get().floatValue()); + + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + + GL32.glUniform1i(this.gDepthMapUniform, 0); + } + + + //========// + // render // + //========// + + @Override + protected void onRender() + { + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.FrameBuffer); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_BLEND); + + ScreenQuad.INSTANCE.render(); + } +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java index 6d506cef7..f4f08eccd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java @@ -19,7 +19,7 @@ package com.seibel.distanthorizons.core.render.vertexFormat; -import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL32; /** * This object is used to build LodVertexFormats. @@ -80,13 +80,13 @@ public class LodVertexFormatElement public enum DataType { - FLOAT(4, "Float", GL11.GL_FLOAT), - UBYTE(1, "Unsigned Byte", GL11.GL_UNSIGNED_BYTE), - BYTE(1, "Byte", GL11.GL_BYTE), - USHORT(2, "Unsigned Short", GL11.GL_UNSIGNED_SHORT), - SHORT(2, "Short", GL11.GL_SHORT), - UINT(4, "Unsigned Int", GL11.GL_UNSIGNED_INT), - INT(4, "Int", GL11.GL_INT); + FLOAT(4, "Float", GL32.GL_FLOAT), + UBYTE(1, "Unsigned Byte", GL32.GL_UNSIGNED_BYTE), + BYTE(1, "Byte", GL32.GL_BYTE), + USHORT(2, "Unsigned Short", GL32.GL_UNSIGNED_SHORT), + SHORT(2, "Short", GL32.GL_SHORT), + UINT(4, "Unsigned Int", GL32.GL_UNSIGNED_INT), + INT(4, "Int", GL32.GL_INT); private final int size; private final String name;