feat: Implement basic framebuffer for LODs

This commit is contained in:
Steveplays28
2023-09-28 15:58:16 +02:00
parent c46e12fb7a
commit a36b231ce8
4 changed files with 93 additions and 57 deletions
@@ -30,6 +30,7 @@ public class GLState
public int vbo;
public int ebo;
public int[] fbo;
public int depthBuffer;
public int texture2D;
/** IE: GL_TEXTURE0, GL_TEXTURE1, etc. */
public int activeTextureNumber;
@@ -55,9 +56,19 @@ public class GLState
public int polyMode;
public GLState() {
public GLState()
{
this.fbo = new int[FBO_MAX];
for (int i = 0; i < FBO_MAX; i++)
{
this.fbo[i] = GL32.glGenFramebuffers();
}
GL32.glEnable(GL32.GL_DEPTH_TEST);
GL32.glDepthFunc(GL32.GL_LESS);
GL32.glDepthMask(true);
this.saveState();
}
@@ -69,18 +80,11 @@ public class GLState
this.ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING);
GL32.glGetIntegerv(GL32.GL_FRAMEBUFFER_BINDING, this.fbo);
this.texture2D = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
this.activeTextureNumber = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
GL32.glActiveTexture(GL32.GL_TEXTURE0);
this.texture0 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
GL32.glActiveTexture(GL32.GL_TEXTURE1);
this.texture1 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
GL32.glActiveTexture(this.activeTextureNumber);
this.texture0 = GL32.glGenTextures();
this.texture1 = GL32.glGenTextures();
this.blend = GL32.glIsEnabled(GL32.GL_BLEND);
this.blendEqRGB = GL32.glGetInteger(GL32.GL_BLEND_EQUATION_RGB);
this.blendEqAlpha = GL32.glGetInteger(GL32.GL_BLEND_EQUATION_ALPHA);
@@ -106,7 +110,7 @@ public class GLState
public String toString()
{
return "GLState{" +
"program=" + this.program + ", vao=" + this.vao + ", vbo=" + this.vbo + ", ebo=" + this.ebo + ", fbo=" + this.fbo[0] +
"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) +
", blend=" + this.blend + ", blendMode=" + GLEnums.getString(this.blendSrcColor) + "," + GLEnums.getString(this.blendDstColor) +
", depth=" + this.depth +
@@ -118,23 +122,32 @@ public class GLState
'}';
}
public void RestoreFrameBuffer()
public void restoreFrameBuffer()
{
// explicitly unbinding the frame buffer is necessary to prevent GL_CLEAR calls from hitting the wrong buffer
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0);
//GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0);
for (int i = 0; i < FBO_MAX; i++)
{
int buffer = this.fbo[i];
if (i > 0 && buffer == 0) break;
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, GL32.glIsFramebuffer(buffer) ? buffer : 0);
}
// Depth buffer
this.depthBuffer = GL32.glGenRenderbuffers();
GL32.glBindRenderbuffer(GL32.GL_RENDERBUFFER, this.depthBuffer);
GL32.glRenderbufferStorage(GL32.GL_RENDERBUFFER, GL32.GL_DEPTH_COMPONENT, 1920, 1080);
// Framebuffer
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fbo[0]);
//GL32.glFramebufferTexture(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, this.texture0, 0);
//for (int i = 0; i < FBO_MAX; i++)
//{
// int buffer = this.fbo[i];
// if (i > 0 && buffer == 0) break;
//
// GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, GL32.glIsFramebuffer(buffer) ? buffer : 0);
//}
}
public void restore()
{
this.RestoreFrameBuffer();
this.restoreFrameBuffer();
if (this.blend)
{
@@ -156,24 +169,14 @@ public class GLState
GL32.glBindVertexArray(GL32.glIsVertexArray(this.vao) ? this.vao : 0);
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, GL32.glIsBuffer(this.vbo) ? this.vbo : 0);
GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, GL32.glIsBuffer(this.ebo) ? this.ebo: 0);
GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, GL32.glIsBuffer(this.ebo) ? this.ebo : 0);
GL32.glUseProgram(GL32.glIsProgram(this.program) ? this.program : 0);
GL32.glDepthMask(this.writeToDepthBuffer);
//GL32.glDepthMask(this.writeToDepthBuffer);
//GL32.glBlendFunc(this.blendSrcColor, this.blendDstColor);
GL32.glBlendEquationSeparate(this.blendEqRGB, this.blendEqAlpha);
GL32.glBlendFuncSeparate(this.blendSrcColor, this.blendDstColor, this.blendSrcAlpha, this.blendDstAlpha);
if (this.depth)
{
GL32.glEnable(GL32.GL_DEPTH_TEST);
}
else
{
GL32.glDisable(GL32.GL_DEPTH_TEST);
}
GL32.glDepthFunc(this.depthFunc);
if (this.stencil)
{
GL32.glEnable(GL32.GL_STENCIL_TEST);
@@ -196,4 +199,5 @@ public class GLState
GL32.glCullFace(this.cullMode);
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, this.polyMode);
}
}
@@ -19,8 +19,6 @@
package com.seibel.distanthorizons.core.render.renderer;
import java.awt.Color;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
@@ -50,6 +50,7 @@ import org.apache.logging.log4j.LogManager;
import org.lwjgl.opengl.GL32;
import java.awt.*;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@@ -89,7 +90,7 @@ public class LodRenderer
if (!GL32.glIsProgram(this.shaderProgram.id))
{
throw new IllegalStateException("No GL program exists with the ID: ["+this.shaderProgram.id+"]. This either means a shader program was freed while it was still in use or was never created.");
throw new IllegalStateException("No GL program exists with the ID: [" + this.shaderProgram.id + "]. This either means a shader program was freed while it was still in use or was never created.");
}
this.shaderProgram.bind();
@@ -142,7 +143,39 @@ public class LodRenderer
public QuadElementBuffer quadIBO = null;
public boolean isSetupComplete = false;
public LodRenderer(RenderBufferHandler bufferHandler) { this.bufferHandler = bufferHandler; }
private final int framebufferId;
private final int colorTextureId;
public LodRenderer(RenderBufferHandler bufferHandler)
{
this.bufferHandler = bufferHandler;
this.framebufferId = GL32.glGenFramebuffers();
this.colorTextureId = GL32.glGenTextures();
int renderBufferId = GL32.glGenRenderbuffers();
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.framebufferId);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.colorTextureId);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D,
0,
GL32.GL_RGBA,
MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight(),
0,
GL32.GL_RGBA,
GL32.GL_UNSIGNED_BYTE,
(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_DRAW_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.colorTextureId, 0);
GL32.glBindRenderbuffer(GL32.GL_RENDERBUFFER, renderBufferId);
GL32.glRenderbufferStorage(GL32.GL_RENDERBUFFER, GL32.GL_DEPTH_COMPONENT32, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
GL32.glFramebufferRenderbuffer(GL32.GL_DRAW_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_RENDERBUFFER, renderBufferId);
//GL32.glBindTexture(GL32.GL_TEXTURE_2D, 0);
}
private boolean rendererClosed = false;
public void close()
@@ -200,19 +233,15 @@ public class LodRenderer
// get MC's shader program and save MC's render state so we can restore it later
// Get DH's GL state
LagSpikeCatcher drawSaveGLState = new LagSpikeCatcher();
GLState minecraftGlState = new GLState();
//GLState minecraftGlState = new GLState();
if (ENABLE_DUMP_GL_STATE)
{
tickLogger.debug("Saving GL state: " + minecraftGlState);
//tickLogger.debug("Saving GL state: " + minecraftGlState);
}
drawSaveGLState.end("drawSaveGLState");
// make sure everything has been initialized
GLProxy glProxy = GLProxy.getInstance();
//===================//
// draw params setup //
@@ -220,8 +249,12 @@ public class LodRenderer
profiler.push("LOD draw setup");
/*---------Set GL State--------*/
GL32.glViewport(0, 0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, 0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.colorTextureId);
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.framebufferId);
GL32.glViewport(0,0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
if (renderWireframe)
{
@@ -243,7 +276,7 @@ public class LodRenderer
GL32.glDisable(GL32.GL_BLEND); // We render opaque first, then transparent
GL32.glDepthMask(true);
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
//GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
/*---------Bind required objects--------*/
// Setup LodRenderProgram and the LightmapTexture if it has not yet been done
@@ -307,13 +340,13 @@ public class LodRenderer
{
profiler.popPush("LOD SSAO");
SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix);
SSAORenderer.INSTANCE.render(minecraftGlState, partialTicks);
//SSAORenderer.INSTANCE.render(minecraftGlState, partialTicks);
}
profiler.popPush("LOD Fog");
FogShader.INSTANCE.setModelViewProjectionMatrix(modelViewProjectionMatrix);
FogShader.INSTANCE.render(partialTicks);
//FogShader.INSTANCE.render(partialTicks);
// DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker
@@ -327,7 +360,7 @@ public class LodRenderer
this.bufferHandler.renderTransparent(this);
GL32.glDepthMask(true); // Apparently the depth mask state is stored in the FBO, so glState fails to restore it...
FogShader.INSTANCE.render(partialTicks);
//FogShader.INSTANCE.render(partialTicks);
}
drawLagSpikeCatcher.end("LodDraw");
@@ -346,7 +379,8 @@ public class LodRenderer
this.quadIBO.unbind();
}
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, 0);
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0);
GL32.glViewport(0,0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
this.shaderProgram.unbind();
@@ -358,9 +392,9 @@ public class LodRenderer
profiler.popPush("LOD cleanup");
}
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
//GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
minecraftGlState.restore();
//minecraftGlState.restore();
drawCleanup.end("LodDrawCleanup");
// end of internal LOD profiling
@@ -447,7 +481,7 @@ public class LodRenderer
this.isSetupComplete = false;
GLProxy.getInstance().recordOpenGlCall(() ->
GLProxy.getInstance().recordOpenGlCall(() ->
{
EVENT_LOGGER.info("Renderer Cleanup Started");
@@ -109,7 +109,7 @@ public class SSAORenderer
SSAOShader.INSTANCE.FrameBuffer = this.ssaoFramebuffer;
SSAOShader.INSTANCE.render(partialTicks);
primaryState.RestoreFrameBuffer();
primaryState.restoreFrameBuffer();
SSAOApplyShader.INSTANCE.BufferTexture = this.ssaoTexture;
SSAOApplyShader.INSTANCE.render(partialTicks);