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..a3e9f2c09
--- /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);
+ }
+
+ ScreenQuad.INSTANCE.bind();
+
+ SSAOShader.INSTANCE.render(partialTicks, ssaoFramebuffer);
+
+ primaryState.RestoreFrameBuffer();
+
+ SSAOApplyShader.INSTANCE.render(partialTicks, ssaoTexture);
+
+ 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..774a3a289
--- /dev/null
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/ScreenQuad.java
@@ -0,0 +1,94 @@
+/*
+ * 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 bind()
+ {
+ this.init();
+
+ this.va.bind();
+ this.va.bindBufferToAllBindingPoint(this.boxBuffer.getId());
+ }
+
+ public void render()
+ {
+ 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..3f9155c1d 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,116 +19,26 @@
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;
+ protected ShaderProgram shader;
+
boolean init = false;
- protected AbstractShaderRenderer(ShaderProgram shader)
- {
- this.shader = shader;
- }
+ protected AbstractShaderRenderer() {}
- private void init()
+ public 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();
-
- 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);
-
- 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);
}
public void free()
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..1028942ea 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,57 @@
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 init()
{
- super(new ShaderProgram("shaders/normal.vert", "shaders/test/dark.frag", "fragColor", new String[]{"vPosition", "color"}));
+ super.init();
+
+ this.shader = new ShaderProgram(
+ "shaders/normal.vert",
+ "shaders/test/dark.frag",
+ "fragColor",
+ new String[]{"vPosition", "color"});
}
+ void setShaderUniforms()
+ {
+ GL32.glActiveTexture(GL32.GL_TEXTURE0);
+ GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
+ }
+
+ public void render()
+ {
+ GLState state = new GLState();
+
+ this.init();
+
+ 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();
+
+ ScreenQuad.INSTANCE.bind();
+
+ 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..7349271d8 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,6 +39,8 @@ 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);
@@ -51,15 +56,14 @@ public class FogShader extends AbstractShaderRenderer
public final int fullFogModeUniform;
-
public FogShader(LodFogConfig fogConfig)
{
- super(new ShaderProgram(
+ 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(),
"fragColor", new String[]{"vPosition"}
- ));
+ );
// all uniforms should be tryGet...
// because disabling fog can cause the GLSL to optimize out most (if not all) uniforms
@@ -78,7 +82,7 @@ public class FogShader extends AbstractShaderRenderer
this.nearFogLengthUniform = this.shader.tryGetUniformLocation("nearFogLength");
}
- @Override
+ //@Override
void setShaderUniforms(float partialTicks)
{
this.shader.bind();
@@ -135,4 +139,32 @@ public class FogShader extends AbstractShaderRenderer
this.shader.unbind();
}
-}
+
+ public void render(float partialTicks)
+ {
+ GLState state = new GLState();
+
+ this.init();
+
+ 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);
+
+ ScreenQuad.INSTANCE.bind();
+
+ GL32.glActiveTexture(GL32.GL_TEXTURE0);
+ GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
+
+ 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/SSAOApplyShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java
new file mode 100644
index 000000000..fb85a4bb5
--- /dev/null
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java
@@ -0,0 +1,119 @@
+/*
+ * 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();
+
+
+ // 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;
+ }
+
+
+ @Override
+ public void init()
+ {
+ super.init();
+
+ this.shader = new ShaderProgram(
+ "shaders/normal.vert",
+ "shaders/ssao/apply.frag",
+ "fragColor",
+ new String[]{"vPosition"});
+
+ // uniform setup
+ this.applyShaderUniforms.gSSAOMapUniform = this.shader.getUniformLocation("gSSAOMap");
+ this.applyShaderUniforms.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap");
+ this.applyShaderUniforms.gViewSizeUniform = this.shader.tryGetUniformLocation("gViewSize");
+ this.applyShaderUniforms.gBlurRadiusUniform = this.shader.tryGetUniformLocation("gBlurRadius");
+ this.applyShaderUniforms.gNearUniform = this.shader.tryGetUniformLocation("gNear");
+ this.applyShaderUniforms.gFarUniform = this.shader.tryGetUniformLocation("gFar");
+ }
+
+ private void setShaderUniforms(float partialTicks, int ssaoTexture)
+ {
+ 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, ssaoTexture);
+ GL32.glUniform1i(this.applyShaderUniforms.gSSAOMapUniform, 1);
+
+ int blurRadius = Config.Client.Advanced.Graphics.Ssao.blurRadius.get();
+ GL32.glUniform1i(this.applyShaderUniforms.gBlurRadiusUniform, blurRadius);
+
+ if (this.applyShaderUniforms.gViewSizeUniform >= 0)
+ {
+ int width = MC_RENDER.getTargetFrameBufferViewportWidth();
+ int height = MC_RENDER.getTargetFrameBufferViewportHeight();
+ GL32.glUniform2f(this.applyShaderUniforms.gViewSizeUniform, width, height);
+ }
+
+ if (this.applyShaderUniforms.gNearUniform >= 0)
+ {
+ float near = RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks);
+ GL32.glUniform1f(this.applyShaderUniforms.gNearUniform, near);
+ }
+
+ if (this.applyShaderUniforms.gFarUniform >= 0)
+ {
+ float far = (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2));
+ GL32.glUniform1f(this.applyShaderUniforms.gFarUniform, far);
+ }
+ }
+
+ //========//
+ // render //
+ //========//
+
+ public void render(float partialTicks, int ssaoTexture)
+ {
+ this.init();
+
+ this.shader.bind();
+
+ setShaderUniforms(partialTicks, ssaoTexture);
+
+ 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..9fe7e2fbe
--- /dev/null
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java
@@ -0,0 +1,137 @@
+/*
+ * 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 com.seibel.distanthorizons.coreapi.util.math.Mat4f;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL32;
+
+public class SSAOShader extends AbstractShaderRenderer
+{
+ public static SSAOShader INSTANCE = new SSAOShader();
+
+
+ // 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;
+ }
+
+
+ @Override
+ public void init()
+ {
+ super.init();
+
+ this.shader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag",
+ "fragColor", new String[]{"vPosition"});
+
+ // uniform setup
+ this.ssaoShaderUniforms.gProjUniform = this.shader.getUniformLocation("gProj");
+ this.ssaoShaderUniforms.gInvProjUniform = this.shader.getUniformLocation("gInvProj");
+ this.ssaoShaderUniforms.gSampleCountUniform = this.shader.getUniformLocation("gSampleCount");
+ this.ssaoShaderUniforms.gRadiusUniform = this.shader.getUniformLocation("gRadius");
+ this.ssaoShaderUniforms.gStrengthUniform = this.shader.getUniformLocation("gStrength");
+ this.ssaoShaderUniforms.gMinLightUniform = this.shader.getUniformLocation("gMinLight");
+ this.ssaoShaderUniforms.gBiasUniform = this.shader.getUniformLocation("gBias");
+ this.ssaoShaderUniforms.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap");
+ }
+
+ void setShaderUniforms(float partialTicks)
+ {
+ int width = MC_RENDER.getTargetFrameBufferViewportWidth();
+ int height = MC_RENDER.getTargetFrameBufferViewportHeight();
+ 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();
+
+ this.shader.setUniform(this.ssaoShaderUniforms.gProjUniform, perspective);
+
+ this.shader.setUniform(this.ssaoShaderUniforms.gInvProjUniform, invertedPerspective);
+
+ this.shader.setUniform(this.ssaoShaderUniforms.gSampleCountUniform,
+ Config.Client.Advanced.Graphics.Ssao.sampleCount.get());
+
+ this.shader.setUniform(this.ssaoShaderUniforms.gRadiusUniform,
+ Config.Client.Advanced.Graphics.Ssao.radius.get().floatValue());
+
+ this.shader.setUniform(this.ssaoShaderUniforms.gStrengthUniform,
+ Config.Client.Advanced.Graphics.Ssao.strength.get().floatValue());
+
+ this.shader.setUniform(this.ssaoShaderUniforms.gMinLightUniform,
+ Config.Client.Advanced.Graphics.Ssao.minLight.get().floatValue());
+
+ this.shader.setUniform(this.ssaoShaderUniforms.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.ssaoShaderUniforms.gDepthMapUniform, 0);
+ }
+
+
+ //========//
+ // render //
+ //========//
+
+ public void render(float partialTicks, int ssaoFramebuffer)
+ {
+ this.init();
+
+ int width = MC_RENDER.getTargetFrameBufferViewportWidth();
+ int height = MC_RENDER.getTargetFrameBufferViewportHeight();
+
+ this.shader.bind();
+
+ setShaderUniforms(partialTicks);
+
+ GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer);
+ GL32.glViewport(0, 0, width, height);
+ GL32.glDisable(GL32.GL_SCISSOR_TEST);
+ GL32.glDisable(GL32.GL_DEPTH_TEST);
+ GL32.glDisable(GL11.GL_BLEND);
+
+ ScreenQuad.INSTANCE.render();
+
+ shader.unbind();
+ }
+}