From 7325d57e8802557019bd8e6ab7115f9ad157fb30 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 5 Feb 2026 17:36:40 -0600 Subject: [PATCH] Make GLState AutoClosable for more robustness --- .../core/render/glObject/GLState.java | 49 +++---- .../core/render/renderer/DhFadeRenderer.java | 1 - .../core/render/renderer/FogRenderer.java | 41 +++--- .../core/render/renderer/SSAORenderer.java | 39 +++--- .../render/renderer/VanillaFadeRenderer.java | 10 +- .../renderer/shaders/DhApplyShader.java | 125 +++++++++--------- 6 files changed, 126 insertions(+), 139 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java index 4ea26061e..7029b007e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java @@ -23,14 +23,11 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper; import org.lwjgl.opengl.GL32; -// TODO make this Closable or AutoClosable so it can be used with try-resource blocks -public class GLState +public class GLState implements AutoCloseable { private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class); - private static final int FBO_MAX = 4; - public int program; public int vao; public int vbo; @@ -132,26 +129,8 @@ public class GLState this.polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE); } - @Override - public String toString() - { - return "GLState{" + - "program=" + this.program + ", vao=" + this.vao + ", vbo=" + this.vbo + ", ebo=" + this.ebo + ", fbo=" + this.fbo + - ", text=" + GLEnums.getString(this.texture2D) + "@" + this.activeTextureNumber + ", text0=" + GLEnums.getString(this.texture0) + - ", FB text0=" + this.frameBufferTexture0 + - ", FB text1=" + this.frameBufferTexture1 + - ", FB depth=" + this.frameBufferDepthTexture + - ", blend=" + this.blend + ", scissor=" + this.scissor + ", blendMode=" + GLEnums.getString(this.blendSrcColor) + "," + GLEnums.getString(this.blendDstColor) + - ", depth=" + this.depth + - ", depthFunc=" + GLEnums.getString(this.depthFunc) + ", stencil=" + this.stencil + - ", stencilFunc=" + GLEnums.getString(this.stencilFunc) + ", stencilRef=" + this.stencilRef + ", stencilMask=" + this.stencilMask + - ", view={x:" + this.view[0] + ", y:" + this.view[1] + - ", w:" + this.view[2] + ", h:" + this.view[3] + "}" + ", cull=" + this.cull + - ", cullMode=" + GLEnums.getString(this.cullMode) + ", polyMode=" + GLEnums.getString(this.polyMode) + - '}'; - } - - public void restore() + @Override + public void close() { // explicitly unbinding the frame buffer is necessary to prevent GL_CLEAR calls from hitting the wrong buffer GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0); @@ -255,4 +234,26 @@ public class GLState GL32.glCullFace(this.cullMode); GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, this.polyMode); } + + @Override + public String toString() + { + return "GLState{" + + "program=" + this.program + ", vao=" + this.vao + ", vbo=" + this.vbo + ", ebo=" + this.ebo + ", fbo=" + this.fbo + + ", text=" + GLEnums.getString(this.texture2D) + "@" + this.activeTextureNumber + ", text0=" + GLEnums.getString(this.texture0) + + ", FB text0=" + this.frameBufferTexture0 + + ", FB text1=" + this.frameBufferTexture1 + + ", FB depth=" + this.frameBufferDepthTexture + + ", blend=" + this.blend + ", scissor=" + this.scissor + ", blendMode=" + GLEnums.getString(this.blendSrcColor) + "," + GLEnums.getString(this.blendDstColor) + + ", depth=" + this.depth + + ", depthFunc=" + GLEnums.getString(this.depthFunc) + ", stencil=" + this.stencil + + ", stencilFunc=" + GLEnums.getString(this.stencilFunc) + ", stencilRef=" + this.stencilRef + ", stencilMask=" + this.stencilMask + + ", view={x:" + this.view[0] + ", y:" + this.view[1] + + ", w:" + this.view[2] + ", h:" + this.view[3] + "}" + ", cull=" + this.cull + + ", cullMode=" + GLEnums.getString(this.cullMode) + ", polyMode=" + GLEnums.getString(this.polyMode) + + '}'; + } + + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhFadeRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhFadeRenderer.java index 8461254bb..ad0d1d298 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhFadeRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhFadeRenderer.java @@ -22,7 +22,6 @@ package com.seibel.distanthorizons.core.render.renderer; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.renderer.shaders.DhFadeShader; import com.seibel.distanthorizons.core.render.renderer.shaders.FadeApplyShader; import com.seibel.distanthorizons.core.util.math.Mat4f; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java index 692e17877..f649b7a05 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java @@ -109,29 +109,28 @@ public class FogRenderer public void render(Mat4f modelViewProjectionMatrix, float partialTicks) { - // needed in MC 1.16.5 probably due to MC not manually setting each GL state they need before the next rendering step - GLState state = new GLState(); - - this.init(); - - // resize the framebuffer if necessary - int width = MC_RENDER.getTargetFramebufferViewportWidth(); - int height = MC_RENDER.getTargetFramebufferViewportHeight(); - if (this.width != width || this.height != height) + // GLState needed in MC 1.16.5 probably due to MC not manually setting each GL state they need before the next rendering step + try (GLState state = new GLState()) { - this.width = width; - this.height = height; - this.createFramebuffer(width, height); + this.init(); + + // resize the framebuffer if necessary + 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); + } + + FogShader.INSTANCE.frameBuffer = this.fogFramebuffer; + FogShader.INSTANCE.setProjectionMatrix(modelViewProjectionMatrix); + FogShader.INSTANCE.render(partialTicks); + + FogApplyShader.INSTANCE.fogTexture = this.fogTexture; + FogApplyShader.INSTANCE.render(partialTicks); } - - FogShader.INSTANCE.frameBuffer = this.fogFramebuffer; - FogShader.INSTANCE.setProjectionMatrix(modelViewProjectionMatrix); - FogShader.INSTANCE.render(partialTicks); - - FogApplyShader.INSTANCE.fogTexture = this.fogTexture; - FogApplyShader.INSTANCE.render(partialTicks); - - state.restore(); } public void free() 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 index 211ff8cac..a74dabde3 100644 --- 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 @@ -110,28 +110,27 @@ public class SSAORenderer public void render(Mat4f projectionMatrix, float partialTicks) { - GLState state = new GLState(); - - this.init(); - - // resize the framebuffer if necessary - int width = MC_RENDER.getTargetFramebufferViewportWidth(); - int height = MC_RENDER.getTargetFramebufferViewportHeight(); - if (this.width != width || this.height != height) + try(GLState state = new GLState()) { - this.width = width; - this.height = height; - this.createFramebuffer(width, height); + this.init(); + + // resize the framebuffer if necessary + 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.setProjectionMatrix(projectionMatrix); + SSAOShader.INSTANCE.render(partialTicks); + + SSAOApplyShader.INSTANCE.ssaoTexture = this.ssaoTexture; + SSAOApplyShader.INSTANCE.render(partialTicks); } - - SSAOShader.INSTANCE.frameBuffer = this.ssaoFramebuffer; - SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix); - SSAOShader.INSTANCE.render(partialTicks); - - SSAOApplyShader.INSTANCE.ssaoTexture = this.ssaoTexture; - SSAOApplyShader.INSTANCE.render(partialTicks); - - state.restore(); } public void free() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/VanillaFadeRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/VanillaFadeRenderer.java index 37bf514cf..f1c1d5a5a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/VanillaFadeRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/VanillaFadeRenderer.java @@ -136,9 +136,7 @@ public class VanillaFadeRenderer profiler.push("DH-Vanilla Fade"); - GLState mcState = new GLState(); - - try + try(GLState mcState = new GLState()) { profiler.push("Vanilla Fade Generate"); @@ -178,12 +176,6 @@ public class VanillaFadeRenderer { LOGGER.error("Unexpected error during fade render, error: ["+e.getMessage()+"].", e); } - finally - { - // make sure we always revert to MC's state to prevent GL state corruption - // this is especially important on MC 1.16.5 or when other rendering mods are present - mcState.restore(); - } } public void free() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DhApplyShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DhApplyShader.java index ce62adcab..9b74d8c5e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DhApplyShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DhApplyShader.java @@ -101,36 +101,35 @@ public class DhApplyShader extends AbstractShaderRenderer } - GLState state = new GLState(); - - GLMC.disableDepthTest(); - - // blending isn't needed, we're manually merging the MC and DH textures - // Note: this prevents the sun/moon and stars from rendering through transparent LODs, - // however this also fixes transparent LODs from glowing when rendered against the sky during the day - GLMC.disableBlend(); - - // old blending logic in case it's ever needed: - //GLMC.enableBlend(); - //GL32.glBlendEquation(GL32.GL_FUNC_ADD); - //GLMC.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); - - GLMC.glActiveTexture(GL32.GL_TEXTURE0); - GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveColorTextureId()); - GL32.glUniform1i(this.gDhColorTextureUniform, 0); - - GLMC.glActiveTexture(GL32.GL_TEXTURE1); - GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId()); - GL32.glUniform1i(this.gDepthMapUniform, 1); - - // Copy to MC's framebuffer - GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, targetFrameBuffer); - - ScreenQuad.INSTANCE.render(); - - - // restore everything, except at this point the MC framebuffer should now be used instead - state.restore(); + try (GLState state = new GLState()) + { + + GLMC.disableDepthTest(); + + // blending isn't needed, we're manually merging the MC and DH textures + // Note: this prevents the sun/moon and stars from rendering through transparent LODs, + // however this also fixes transparent LODs from glowing when rendered against the sky during the day + GLMC.disableBlend(); + + // old blending logic in case it's ever needed: + //GLMC.enableBlend(); + //GL32.glBlendEquation(GL32.GL_FUNC_ADD); + //GLMC.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); + + GLMC.glActiveTexture(GL32.GL_TEXTURE0); + GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveColorTextureId()); + GL32.glUniform1i(this.gDhColorTextureUniform, 0); + + GLMC.glActiveTexture(GL32.GL_TEXTURE1); + GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId()); + GL32.glUniform1i(this.gDepthMapUniform, 1); + + // Copy to MC's framebuffer + GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, targetFrameBuffer); + + ScreenQuad.INSTANCE.render(); + } + // everything's been restored, except at this point the MC framebuffer should now be used instead GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, targetFrameBuffer); } @@ -156,40 +155,38 @@ public class DhApplyShader extends AbstractShaderRenderer - GLState state = new GLState(); - - GLMC.disableDepthTest(); - - // blending isn't needed, we're just directly merging the MC and DH textures - // Note: this prevents the sun/moon and stars from rendering through transparent LODs, - // however this also fixes - GLMC.disableBlend(); - - // old blending logic in case it's ever needed: - //GLMC.enableBlend(); - //GL32.glBlendEquation(GL32.GL_FUNC_ADD); - //GLMC.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); - - GLMC.glActiveTexture(GL32.GL_TEXTURE0); - GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveColorTextureId()); - GL32.glUniform1i(this.gDhColorTextureUniform, 0); - - GLMC.glActiveTexture(GL32.GL_TEXTURE1); - GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId()); - GL32.glUniform1i(this.gDepthMapUniform, 1); - - - - GL32.glFramebufferTexture(GL32.GL_DRAW_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, targetColorTextureId, 0); - - // Copy to MC's texture via MC's framebuffer - GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, dhFrameBufferId); - - ScreenQuad.INSTANCE.render(); - - - // restore everything, except at this point the MC framebuffer should now be used instead - state.restore(); + try (GLState state = new GLState()) + { + GLMC.disableDepthTest(); + + // blending isn't needed, we're just directly merging the MC and DH textures + // Note: this prevents the sun/moon and stars from rendering through transparent LODs, + // however this also fixes + GLMC.disableBlend(); + + // old blending logic in case it's ever needed: + //GLMC.enableBlend(); + //GL32.glBlendEquation(GL32.GL_FUNC_ADD); + //GLMC.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); + + GLMC.glActiveTexture(GL32.GL_TEXTURE0); + GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveColorTextureId()); + GL32.glUniform1i(this.gDhColorTextureUniform, 0); + + GLMC.glActiveTexture(GL32.GL_TEXTURE1); + GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId()); + GL32.glUniform1i(this.gDepthMapUniform, 1); + + + + GL32.glFramebufferTexture(GL32.GL_DRAW_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, targetColorTextureId, 0); + + // Copy to MC's texture via MC's framebuffer + GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, dhFrameBufferId); + + ScreenQuad.INSTANCE.render(); + } + // everything's been restored, except at this point the MC framebuffer should now be used instead GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, mcFrameBufferId); }