This commit is contained in:
s809
2023-08-13 01:53:06 +05:00
13 changed files with 484 additions and 458 deletions
@@ -489,7 +489,7 @@ public class ClientApi
profiler.push("Render" + (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEFAULT ? "-lods" : "-debug"));
try
{
if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEFAULT)
@@ -508,7 +508,9 @@ public class ClientApi
}
else if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEBUG)
{
profiler.push("Render Debug");
ClientApi.testRenderer.render();
profiler.pop();
}
// the other rendererMode is DISABLED
}
@@ -522,7 +524,6 @@ public class ClientApi
MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues.");
MC.sendChatMessage("\u00A74Exception detail: " + e);
}
profiler.pop();
}
catch (Exception e)
{
@@ -164,13 +164,14 @@ public class LodFogConfig
public StringBuilder loadAndProcessFragShader(String path, boolean absoluteFilePath)
{
StringBuilder str = makeRuntimeDefine();
generateRuntimeShaderCode(Shader.loadFile(path, absoluteFilePath, str));
StringBuilder stringBuilder = this.makeRuntimeDefine();
this.generateRuntimeShaderCode(Shader.loadFile(path, absoluteFilePath, stringBuilder));
if (DEBUG_DUMP_GENERATED_CODE)
{
try (FileOutputStream file = new FileOutputStream("debugGenerated.frag", false))
{
file.write(str.toString().getBytes(StandardCharsets.UTF_8));
file.write(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
GLProxy.GL_LOGGER.info("Debug dumped generated code to debugGenerated.frag for {}", path);
}
catch (IOException e)
@@ -178,7 +179,8 @@ public class LodFogConfig
GLProxy.GL_LOGGER.warn("Failed to debug dump generated code to file for {}", path);
}
}
return str;
return stringBuilder;
}
/** Generates the necessary constants for a fragment shader */
@@ -21,8 +21,9 @@ package com.seibel.distanthorizons.core.render.glObject;
import org.lwjgl.opengl.GL32;
public class GLState {
public class GLState
{
public int prog;
public int vao;
public int vbo;
@@ -45,89 +46,109 @@ public class GLState {
public boolean cull;
public int cullMode;
public int polyMode;
public void saveState() {
prog = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM);
vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING);
fbo = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
text = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
activeTex = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
public GLState() { this.saveState(); }
public void saveState()
{
this.prog = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM);
this.vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
this.vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
this.ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING);
this.fbo = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
this.text = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
this.activeTex = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
GL32.glActiveTexture(GL32.GL_TEXTURE0);
text0 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
GL32.glActiveTexture(activeTex);
blend = GL32.glIsEnabled(GL32.GL_BLEND);
blendSrc = GL32.glGetInteger(GL32.GL_BLEND_SRC);
blendDst = GL32.glGetInteger(GL32.GL_BLEND_DST);
depth = GL32.glIsEnabled(GL32.GL_DEPTH_TEST);
depthWrite = GL32.glGetInteger(GL32.GL_DEPTH_WRITEMASK) == GL32.GL_TRUE;
depthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC);
stencil = GL32.glIsEnabled(GL32.GL_STENCIL_TEST);
stencilFunc = GL32.glGetInteger(GL32.GL_STENCIL_FUNC);
stencilRef = GL32.glGetInteger(GL32.GL_STENCIL_REF);
stencilMask = GL32.glGetInteger(GL32.GL_STENCIL_VALUE_MASK);
view = new int[4];
GL32.glGetIntegerv(GL32.GL_VIEWPORT, view);
cull = GL32.glIsEnabled(GL32.GL_CULL_FACE);
cullMode = GL32.glGetInteger(GL32.GL_CULL_FACE_MODE);
polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE);
this.text0 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
GL32.glActiveTexture(this.activeTex);
this.blend = GL32.glIsEnabled(GL32.GL_BLEND);
this.blendSrc = GL32.glGetInteger(GL32.GL_BLEND_SRC);
this.blendDst = GL32.glGetInteger(GL32.GL_BLEND_DST);
this.depth = GL32.glIsEnabled(GL32.GL_DEPTH_TEST);
this.depthWrite = GL32.glGetInteger(GL32.GL_DEPTH_WRITEMASK) == GL32.GL_TRUE;
this.depthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC);
this.stencil = GL32.glIsEnabled(GL32.GL_STENCIL_TEST);
this.stencilFunc = GL32.glGetInteger(GL32.GL_STENCIL_FUNC);
this.stencilRef = GL32.glGetInteger(GL32.GL_STENCIL_REF);
this.stencilMask = GL32.glGetInteger(GL32.GL_STENCIL_VALUE_MASK);
this.view = new int[4];
GL32.glGetIntegerv(GL32.GL_VIEWPORT, this.view);
this.cull = GL32.glIsEnabled(GL32.GL_CULL_FACE);
this.cullMode = GL32.glGetInteger(GL32.GL_CULL_FACE_MODE);
this.polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE);
}
@Override
public String toString() {
return "GLState{" + "prog=" + prog + ", vao=" + vao + ", vbo=" + vbo + ", ebo=" + ebo + ", fbo=" + fbo +
", text=" + GLEnums.getString(text) + "@"+activeTex+", text0=" + GLEnums.getString(text0) +
", blend=" + blend + ", blendMode=" + GLEnums.getString(blendSrc) + "," + GLEnums.getString(blendDst) +
", depth=" + depth +
", depthFunc=" + GLEnums.getString(depthFunc) + ", stencil=" + stencil + ", stencilFunc=" +
GLEnums.getString(stencilFunc) + ", stencilRef=" + stencilRef + ", stencilMask=" + stencilMask +
", view={x:" + view[0] + ", y:" + view[1] +
", w:" + view[2] + ", h:" + view[3] + "}" + ", cull=" + cull + ", cullMode="
+ GLEnums.getString(cullMode) + ", polyMode=" + GLEnums.getString(polyMode) + '}';
public String toString()
{
return "GLState{"+
"prog="+this.prog+", vao="+this.vao+", vbo="+this.vbo+", ebo="+this.ebo+", fbo="+this.fbo +
", text="+GLEnums.getString(this.text)+"@"+this.activeTex+", text0="+GLEnums.getString(this.text0) +
", blend="+this.blend+", blendMode="+GLEnums.getString(this.blendSrc)+","+GLEnums.getString(this.blendDst) +
", 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() {
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, fbo);
if (blend) {
GL32.glEnable(GL32.GL_BLEND);
} else {
GL32.glDisable(GL32.GL_BLEND);
}
public void restore()
{
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fbo);
if (this.blend)
{
GL32.glEnable(GL32.GL_BLEND);
}
else
{
GL32.glDisable(GL32.GL_BLEND);
}
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, text0);
GL32.glActiveTexture(activeTex);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, text);
GL32.glBindVertexArray(vao);
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, vbo);
GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, ebo);
GL32.glUseProgram(prog);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.text0);
GL32.glActiveTexture(this.activeTex);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.text);
GL32.glBindVertexArray(this.vao);
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.vbo);
GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, this.ebo);
GL32.glUseProgram(this.prog);
GL32.glDepthMask(depthWrite);
GL32.glBlendFunc(blendSrc, blendDst);
if (depth) {
GL32.glEnable(GL32.GL_DEPTH_TEST);
} else {
GL32.glDisable(GL32.GL_DEPTH_TEST);
GL32.glDepthMask(this.depthWrite);
GL32.glBlendFunc(this.blendSrc, this.blendDst);
if (this.depth)
{
GL32.glEnable(GL32.GL_DEPTH_TEST);
}
GL32.glDepthFunc(depthFunc);
if (stencil) {
GL32.glEnable(GL32.GL_STENCIL_TEST);
} else {
GL32.glDisable(GL32.GL_STENCIL_TEST);
else
{
GL32.glDisable(GL32.GL_DEPTH_TEST);
}
GL32.glStencilFunc(stencilFunc, stencilRef, stencilMask);
GL32.glViewport(view[0], view[1], view[2], view[3]);
if (cull) {
GL32.glEnable(GL32.GL_CULL_FACE);
} else {
GL32.glDisable(GL32.GL_CULL_FACE);
GL32.glDepthFunc(this.depthFunc);
if (this.stencil)
{
GL32.glEnable(GL32.GL_STENCIL_TEST);
}
GL32.glCullFace(cullMode);
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, polyMode);
else
{
GL32.glDisable(GL32.GL_STENCIL_TEST);
}
GL32.glStencilFunc(this.stencilFunc, this.stencilRef, this.stencilMask);
GL32.glViewport(this.view[0], this.view[1], this.view[2], this.view[3]);
if (this.cull)
{
GL32.glEnable(GL32.GL_CULL_FACE);
}
else
{
GL32.glDisable(GL32.GL_CULL_FACE);
}
GL32.glCullFace(this.cullMode);
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, this.polyMode);
}
public GLState() {
saveState();
}
}
@@ -146,7 +146,10 @@ public class ShaderProgram
public int getUniformLocation(CharSequence name)
{
int i = GL32.glGetUniformLocation(id, name);
if (i==-1) throw new RuntimeException("Uniform name not found: "+name);
if (i==-1)
{
throw new RuntimeException("Uniform name not found: "+name);
}
return i;
}
@@ -56,12 +56,6 @@ public class LodRenderProgram extends ShaderProgram
public final int lightMapUniform;
// 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;
// Noise Uniforms
public final int noiseEnabledUniform;
@@ -72,13 +66,13 @@ public class LodRenderProgram extends ShaderProgram
// Debug Uniform
public final int whiteWorldUniform;
public final LodFogConfig fogConfig;
private final LodFogConfig fogConfig;
// This will bind VertexAttribute
public LodRenderProgram(LodFogConfig fogConfig) {
super(() -> Shader.loadFile(fogConfig.earthCurveRatio!=0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH,
false, new StringBuilder()).toString(),
() -> fogConfig.loadAndProcessFragShader(FRAGMENT_SHADER_PATH, false).toString(),
() -> Shader.loadFile(FRAGMENT_SHADER_PATH, false, new StringBuilder()).toString(),
"fragColor", new String[] { "vPosition", "color" });
this.fogConfig = fogConfig;
@@ -90,14 +84,6 @@ public class LodRenderProgram extends ShaderProgram
lightMapUniform = getUniformLocation("lightMap");
// Fog Uniforms
fullFogModeUniform = getUniformLocation("fullFogMode");
fogColorUniform = getUniformLocation("fogColor");
fogScaleUniform = tryGetUniformLocation("fogScale");
fogVerticalScaleUniform = tryGetUniformLocation("fogVerticalScale");
// near
nearFogStartUniform = tryGetUniformLocation("nearFogStart");
nearFogLengthUniform = tryGetUniformLocation("nearFogLength");
// Noise Uniforms
noiseEnabledUniform = getUniformLocation("noiseEnabled");
@@ -139,9 +125,13 @@ public class LodRenderProgram extends ShaderProgram
}
// If not usable, return a new LodFogConfig to be constructed
public LodFogConfig isShaderUsable() {
public LodFogConfig isShaderUsable() // TODO replace with a config listener, look at LodFogConfig for more info
{
LodFogConfig newConfig = LodFogConfig.generateFogConfig();
if (fogConfig.equals(newConfig)) return null;
if (fogConfig.equals(newConfig))
{
return null;
}
return newConfig;
}
@@ -170,9 +160,8 @@ public class LodRenderProgram extends ShaderProgram
vao.unbindBuffersFromAllBindingPoint();
}
public void fillUniformData(Mat4f combinedMatrix, Color fogColor,
int lightmapBindPoint, int worldHeight, int worldYOffset, int lodDrawDistance,
int vanillaDrawDistance, boolean fullFogMode) {
public void fillUniformData(Mat4f combinedMatrix, int lightmapBindPoint, int worldYOffset, int vanillaDrawDistance)
{
super.bind();
vanillaDrawDistance += 32; // Give it a 2 chunk boundary for near fog.
// uniforms
@@ -183,20 +172,10 @@ public class LodRenderProgram extends ShaderProgram
setUniform(lightMapUniform, lightmapBindPoint);
if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float)worldYOffset);
// Fog
setUniform(fullFogModeUniform, fullFogMode ? 1 : 0);
setUniform(fogColorUniform, fogColor);
// Debug
setUniform(whiteWorldUniform, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
float nearFogLen = vanillaDrawDistance * 0.2f / lodDrawDistance;
float nearFogStart = vanillaDrawDistance * (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float)Math.sqrt(2.) : 1.f) / lodDrawDistance;
if (nearFogStartUniform != -1) setUniform(nearFogStartUniform, nearFogStart);
if (nearFogLengthUniform != -1) setUniform(nearFogLengthUniform, nearFogLen);
if (fogScaleUniform != -1) setUniform(fogScaleUniform, 1.f/lodDrawDistance);
if (fogVerticalScaleUniform != -1) setUniform(fogVerticalScaleUniform, 1.f/worldHeight);
}
public void setModelPos(Vec3f modelPos) {
@@ -30,10 +30,8 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.glObject.GLState;
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.core.render.glObject.buffer.QuadElementBuffer;
import com.seibel.distanthorizons.core.render.renderer.shaders.DarkShader;
import com.seibel.distanthorizons.core.render.renderer.shaders.FogShader;
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAORenderer;
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -47,6 +45,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.opengl.GL32;
import java.awt.*;
@@ -56,17 +55,14 @@ import java.util.concurrent.TimeUnit;
/**
* This is where all the magic happens. <br>
* This is where LODs are draw to the world.
*
* @author James Seibel
* @version 2022-8-21
*/
public class LodRenderer
{
public static final ConfigBasedLogger EVENT_LOGGER = new ConfigBasedLogger(LogManager.getLogger(LodRenderer.class),
() -> Config.Client.Advanced.Logging.logRendererBufferEvent.get());
public static ConfigBasedSpamLogger tickLogger = new ConfigBasedSpamLogger(LogManager.getLogger(LodRenderer.class),
() -> Config.Client.Advanced.Logging.logRendererBufferEvent.get(),1);
public static final boolean ENABLE_DRAW_LAG_SPIKE_LOGGING = false;
public static final boolean ENABLE_DUMP_GL_STATE = true;
public static final long DRAW_LAG_SPIKE_THRESHOLD_NS = TimeUnit.NANOSECONDS.convert(20, TimeUnit.MILLISECONDS);
@@ -77,36 +73,46 @@ public class LodRenderer
public static boolean transparencyEnabled = true;
public static boolean fakeOceanFloor = true;
public void setupOffset(DhBlockPos pos) {
public void setupOffset(DhBlockPos pos)
{
Vec3d cam = MC_RENDER.getCameraExactPosition();
Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z));
shaderProgram.setModelPos(modelPos);
// FogShader.INSTANCE.setModelPos(modelPos);
this.shaderProgram.bind();
this.shaderProgram.setModelPos(modelPos);
}
public void drawVbo(GLVertexBuffer vbo) {
public void drawVbo(GLVertexBuffer vbo)
{
vbo.bind();
shaderProgram.bindVertexBuffer(vbo.getId());
GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount()/4)*6,
quadIBO.getType(), 0);
this.shaderProgram.bindVertexBuffer(vbo.getId());
GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount()/4)*6, // TODO what does the 4 and 6 here represent?
this.quadIBO.getType(), 0);
vbo.unbind();
}
public Vec3f getLookVector() {
return MC_RENDER.getLookAtVector();
}
public Vec3f getLookVector() { return MC_RENDER.getLookAtVector(); }
public static class LagSpikeCatcher {
public static class LagSpikeCatcher
{
long timer = System.nanoTime();
public LagSpikeCatcher() {}
public void end(String source) {
if (!ENABLE_DRAW_LAG_SPIKE_LOGGING) return;
timer = System.nanoTime() - timer;
if (timer> DRAW_LAG_SPIKE_THRESHOLD_NS) { //4 ms
EVENT_LOGGER.debug("NOTE: "+source+" took "+Duration.ofNanos(timer)+"!");
public LagSpikeCatcher() { }
public void end(String source)
{
if (!ENABLE_DRAW_LAG_SPIKE_LOGGING)
{
return;
}
this.timer = System.nanoTime() - this.timer;
if (this.timer > DRAW_LAG_SPIKE_THRESHOLD_NS)
{
//4 ms
EVENT_LOGGER.debug("NOTE: " + source + " took " + Duration.ofNanos(this.timer) + "!");
}
}
}
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
@@ -120,16 +126,12 @@ public class LodRenderer
public QuadElementBuffer quadIBO = null;
public boolean isSetupComplete = false;
public LodRenderer(RenderBufferHandler bufferHandler)
{
this.bufferHandler = bufferHandler;
}
public LodRenderer(RenderBufferHandler bufferHandler) { this.bufferHandler = bufferHandler; }
private boolean closeCalled = false;
private boolean rendererClosed = false;
public void close()
{
if (this.closeCalled)
if (this.rendererClosed)
{
EVENT_LOGGER.warn("close() called twice!");
return;
@@ -137,7 +139,7 @@ public class LodRenderer
EVENT_LOGGER.info("Shutting down "+LodRenderer.class.getSimpleName()+"...");
this.closeCalled = true;
this.rendererClosed = true;
GLProxy.getInstance().recordOpenGlCall(this::cleanup);
this.bufferHandler.close();
@@ -146,154 +148,169 @@ public class LodRenderer
public void drawLODs(Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, float partialTicks, IProfilerWrapper profiler)
{
if (closeCalled) {
if (this.rendererClosed)
{
EVENT_LOGGER.error("drawLODs() called after close()!");
return;
}
// get MC's shader program
// Save all MC render state
// get MC's shader program and save MC's render state so we can restore it later
LagSpikeCatcher drawSaveGLState = new LagSpikeCatcher();
GLState currentState = new GLState();
if (ENABLE_DUMP_GL_STATE) {
tickLogger.debug("Saving GL state: {}", currentState);
GLState minecraftGlState = new GLState();
if (ENABLE_DUMP_GL_STATE)
{
tickLogger.debug("Saving GL state: "+minecraftGlState);
}
drawSaveGLState.end("drawSaveGLState");
// make sure everything has been initialized
GLProxy glProxy = GLProxy.getInstance();
//===================//
// draw params setup //
//===================//
profiler.push("LOD draw setup");
/*---------Set GL State--------*/
// Make sure to unbind current VBO so we don't mess up vanilla settings
//GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
GL32.glViewport(0,0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
GL32.glViewport(0, 0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, 0);
// set the required open GL settings
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
if (renderWireframe)
if (renderWireframe)
{
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
//GL32.glDisable(GL32.GL_CULL_FACE);
}
else
else
{
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
GL32.glEnable(GL32.GL_CULL_FACE);
}
GL32.glEnable(GL32.GL_DEPTH_TEST);
// GL32.glDisable(GL32.GL_DEPTH_TEST);
GL32.glDepthFunc(GL32.GL_LESS);
transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled;
fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled;
GL32.glDisable(GL32.GL_BLEND); // We render opaque first, then transparent
GL32.glDepthMask(true);
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
/*---------Bind required objects--------*/
// Setup LodRenderProgram and the LightmapTexture if it has not yet been done
// also binds LightmapTexture, VAO, and ShaderProgram
if (!isSetupComplete) {
setup();
} else {
LodFogConfig newConfig = shaderProgram.isShaderUsable();
if (newConfig != null) {
shaderProgram.free();
shaderProgram = new LodRenderProgram(newConfig);
// FogShader.INSTANCE.free();
// FogShader.INSTANCE = new FogShader(newConfig);
if (!this.isSetupComplete)
{
this.setup();
}
else
{
LodFogConfig newFogConfig = this.shaderProgram.isShaderUsable();
if (newFogConfig != null)
{
this.shaderProgram.free();
this.shaderProgram = new LodRenderProgram(newFogConfig);
FogShader.INSTANCE.free();
FogShader.INSTANCE = new FogShader(newFogConfig);
}
shaderProgram.bind();
this.shaderProgram.bind();
}
GL32.glActiveTexture(GL32.GL_TEXTURE0);
//LightmapTexture lightmapTexture = new LightmapTexture();
/*---------Get required data--------*/
int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks);
/*---------Fill uniform data--------*/
// Fill the uniform data. Note: GL33.GL_TEXTURE0 == texture bindpoint 0
shaderProgram.fillUniformData(modelViewProjectionMatrix,
MC_RENDER.isFogStateSpecial() ? getSpecialFogColor(partialTicks) : getFogColor(partialTicks),
0, MC.getWrappedClientWorld().getHeight(), MC.getWrappedClientWorld().getMinHeight(), RenderUtil.getFarClipPlaneDistanceInBlocks(),
vanillaBlockRenderedDistance, MC_RENDER.isFogStateSpecial());
this.shaderProgram.fillUniformData(modelViewProjectionMatrix, /*Light map = GL_TEXTURE0*/ 0,
MC.getWrappedClientWorld().getMinHeight(), vanillaBlockRenderedDistance);
// Note: Since lightmapTexture is changing every frame, it's faster to recreate it than to reuse the old one.
ILightMapWrapper lightmap = MC_RENDER.getLightmapWrapper();
lightmap.bind();
if (ENABLE_IBO) quadIBO.bind();
//lightmapTexture.fillData(MC_RENDER.getLightmapTextureWidth(), MC_RENDER.getLightmapTextureHeight(), MC_RENDER.getLightmapPixels());
//GL32.glEnable( GL32.GL_POLYGON_OFFSET_FILL );
//GL32.glPolygonOffset( 1f, 1f );
bufferHandler.buildRenderListAndUpdateSections(this.getLookVector());
if (ENABLE_IBO)
{
this.quadIBO.bind();
}
this.bufferHandler.buildRenderListAndUpdateSections(this.getLookVector());
//===========//
// rendering //
//===========//
profiler.popPush("LOD draw");
LagSpikeCatcher draw = new LagSpikeCatcher();
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
DhBlockPos cameraBlockPos = MC_RENDER.getCameraBlockPosition();
Vec3f cameraDir = MC_RENDER.getLookAtVector();
LagSpikeCatcher drawLagSpikeCatcher = new LagSpikeCatcher();
//TODO: Directional culling
bufferHandler.renderOpaque(this);
if (Config.Client.Advanced.Graphics.Quality.ssao.get()) {
// SSAOShader.INSTANCE.render(partialTicks); // For some reason this looks slightly different :/
profiler.popPush("LOD Opaque");
// TODO: Directional culling
this.bufferHandler.renderOpaque(this);
if (Config.Client.Advanced.Graphics.Quality.ssao.get())
{
// broken, causes renderer to crash
// TODO remove duplicate SSAO shader
//SSAOShader.INSTANCE.render(partialTicks); // For some reason this looks slightly different :/
profiler.popPush("LOD SSAO");
SSAORenderer.INSTANCE.render(partialTicks);
}
profiler.popPush("LOD Fog");
// TODO add the model view/projection matrices to the render() function
FogShader.INSTANCE.setModelViewProjectionMatrix(modelViewProjectionMatrix);
FogShader.INSTANCE.render(partialTicks);
// DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker
if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
{
// FogShader.INSTANCE.render(partialTicks);
// DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker
}
//======================//
// render transparency //
//======================//
if (LodRenderer.transparencyEnabled) {
profiler.popPush("LOD Transparent");
GL32.glEnable(GL32.GL_BLEND);
GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
//GL32.glDepthMask(false); // This so that even on incorrect sorting of transparent blocks, it still mostly looks correct
bufferHandler.renderTransparent(this);
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);
}
//if (drawCall==0)
// tickLogger.info("DrawCall Count: {}", drawCount);
drawLagSpikeCatcher.end("LodDraw");
//================//
// render cleanup //
//================//
draw.end("LodDraw");
profiler.popPush("LOD cleanup");
LagSpikeCatcher drawCleanup = new LagSpikeCatcher();
lightmap.unbind();
if (ENABLE_IBO) quadIBO.unbind();
if (ENABLE_IBO)
{
this.quadIBO.unbind();
}
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, 0);
shaderProgram.unbind();
//lightmapTexture.free();
this.shaderProgram.unbind();
DebugRenderer.INSTANCE.render(modelViewProjectionMatrix);
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
currentState.restore();
minecraftGlState.restore();
drawCleanup.end("LodDrawCleanup");
// end of internal LOD profiling
profiler.pop();
tickLogger.incLogTries();
}
@@ -303,22 +320,26 @@ public class LodRenderer
//=================//
/** Setup all render objects - REQUIRES to be in render thread */
private void setup() {
if (isSetupComplete) {
private void setup()
{
if (this.isSetupComplete)
{
EVENT_LOGGER.warn("Renderer setup called but it has already completed setup!");
return;
}
if (!GLProxy.hasInstance()) {
if (!GLProxy.hasInstance())
{
EVENT_LOGGER.warn("Renderer setup called but GLProxy has not yet been setup!");
return;
}
EVENT_LOGGER.info("Setting up renderer");
isSetupComplete = true;
shaderProgram = new LodRenderProgram(LodFogConfig.generateFogConfig());
if (ENABLE_IBO) {
quadIBO = new QuadElementBuffer();
quadIBO.reserve(AbstractRenderBuffer.MAX_QUADS_PER_BUFFER);
this.isSetupComplete = true;
this.shaderProgram = new LodRenderProgram(LodFogConfig.generateFogConfig()); // TODO this doesn't actually use the fog config
if (ENABLE_IBO)
{
this.quadIBO = new QuadElementBuffer();
this.quadIBO.reserve(AbstractRenderBuffer.MAX_QUADS_PER_BUFFER);
}
EVENT_LOGGER.info("Renderer setup complete");
}
@@ -328,16 +349,17 @@ public class LodRenderer
Color fogColor;
if (Config.Client.Advanced.Graphics.Fog.colorMode.get() == EFogColorMode.USE_SKY_COLOR)
{
fogColor = MC_RENDER.getSkyColor();
}
else
{
fogColor = MC_RENDER.getFogColor(partialTicks);
}
return fogColor;
}
private Color getSpecialFogColor(float partialTicks)
{
return MC_RENDER.getSpecialFogColor(partialTicks);
}
private Color getSpecialFogColor(float partialTicks) { return MC_RENDER.getSpecialFogColor(partialTicks); }
@@ -345,22 +367,30 @@ public class LodRenderer
// Cleanup Functions //
//======================//
/** cleanup and free all render objects. REQUIRES to be in render thread
* (Many objects are Native, outside of JVM, and need manual cleanup) */
private void cleanup() {
if (!isSetupComplete) {
/**
* cleanup and free all render objects. REQUIRES to be in render thread
* (Many objects are Native, outside of JVM, and need manual cleanup)
*/
private void cleanup()
{
if (!this.isSetupComplete)
{
EVENT_LOGGER.warn("Renderer cleanup called but Renderer has not completed setup!");
return;
}
if (!GLProxy.hasInstance()) {
EVENT_LOGGER.warn("Renderer Cleanup called but the GLProxy has never been inited!");
if (!GLProxy.hasInstance())
{
EVENT_LOGGER.warn("Renderer Cleanup called but the GLProxy has never been initalized!");
return;
}
isSetupComplete = false;
this.isSetupComplete = false;
EVENT_LOGGER.info("Renderer Cleanup Started");
shaderProgram.free();
// FogShader.INSTANCE.free();
if (quadIBO != null) quadIBO.destroy(false);
this.shaderProgram.free();
if (this.quadIBO != null)
{
this.quadIBO.destroy(false);
}
EVENT_LOGGER.info("Renderer Cleanup Complete");
}
}
@@ -48,7 +48,8 @@ public abstract class AbstractShaderRenderer {
this.applyShader = applyShader;
}
private void init() {
private void init()
{
if (init) return;
init = true;
@@ -61,7 +62,7 @@ public abstract class AbstractShaderRenderer {
// Some shader stuff needs to be set a bit later than
this.postInit();
// Framebuffer
createBuffer();
this.createBuffer();
}
/** Sets all the vertex attributes */
@@ -75,16 +76,19 @@ public abstract class AbstractShaderRenderer {
/** Overwrite if you need to run something on runtime */
void postInit() {};
public void render(float partialTicks) {
// TODO pass in the Model View and Projection Matrices along with the ticks
public void render(float partialTicks)
{
GLState state = new GLState();
init();
this.init();
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
if (this.width != width || this.height != height) {
if (this.width != width || this.height != height)
{
this.width = width;
this.height = height;
createFramebuffer(width, height);
this.createFramebuffer(width, height);
}
@@ -100,64 +104,76 @@ public abstract class AbstractShaderRenderer {
this.setShaderUniforms(partialTicks);
va.bind();
va.bindBufferToAllBindingPoint(boxBuffer.getId());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
if (applyShader != null) {
applyShader.bind();
this.setApplyShaderUniforms(partialTicks);
if (applyShader != null)
{
applyShader.bind();
this.setApplyShaderUniforms(partialTicks);
}
GL32.glEnable(GL11.GL_BLEND);
GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
// explicitly unbinding the frame buffer is necessary to prevent GL_CLEAR calls from hitting the wrong buffer
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0);
state.restore();
}
private void createFramebuffer(int width, int height) {
if (framebuffer != -1) {
GL32.glDeleteFramebuffers(framebuffer);
framebuffer = -1;
private void createFramebuffer(int width, int height)
{
if (this.framebuffer != -1)
{
GL32.glDeleteFramebuffers(this.framebuffer);
this.framebuffer = -1;
}
if (shaderTexture != -1) {
GL32.glDeleteTextures(shaderTexture);
shaderTexture = -1;
if (this.shaderTexture != -1)
{
GL32.glDeleteTextures(this.shaderTexture);
this.shaderTexture = -1;
}
framebuffer = GL32.glGenFramebuffers();
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, framebuffer);
shaderTexture = GL32.glGenTextures();
GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture);
this.framebuffer = GL32.glGenFramebuffers();
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.framebuffer);
this.shaderTexture = GL32.glGenTextures();
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.shaderTexture);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST);
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, shaderTexture, 0);
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.shaderTexture, 0);
}
private void createBuffer() {
ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES);
buffer.order(ByteOrder.nativeOrder());
buffer.asFloatBuffer().put(box_vertices);
buffer.rewind();
boxBuffer = new GLVertexBuffer(false);
boxBuffer.bind();
boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
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() {
this.shader.free();
if (this.applyShader != null)
this.applyShader.free();
public void free()
{
this.shader.free();
if (this.applyShader != null)
{
this.applyShader.free();
}
}
}
@@ -11,22 +11,19 @@ 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.coreapi.util.math.Mat4f;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
import org.lwjgl.opengl.GL32;
import java.awt.*;
public class FogShader extends AbstractShaderRenderer {
public class FogShader extends AbstractShaderRenderer
{
public static FogShader INSTANCE = new FogShader(LodFogConfig.generateFogConfig());
private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class);
// public final int modelOffsetUniform;
// public final int worldYOffsetUniform;
public final int gProjUniform;
public final int gModelViewProjectionUniform;
public final int gDepthMapUniform;
// Fog Uniforms
public final int fogColorUniform;
public final int fogScaleUniform;
@@ -34,68 +31,70 @@ public class FogShader extends AbstractShaderRenderer {
public final int nearFogStartUniform;
public final int nearFogLengthUniform;;
public final int fullFogModeUniform;
public FogShader(LodFogConfig fogConfig) {
// TODO & Note: This code is a bit jank, so try to make it better later (preferably not using something to process the shader)
// This code is just a temp fix so that it looks fine for the time being
// and even with the jank soloution, i cannot get it to work
public FogShader(LodFogConfig fogConfig)
{
super(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" }
));
// modelOffsetUniform = this.shader.getUniformLocation("modelOffset");
// worldYOffsetUniform = this.shader.tryGetUniformLocation("worldYOffset");
gProjUniform = this.shader.getUniformLocation("gProj");
gDepthMapUniform = this.shader.getUniformLocation("gDepthMap");
// all uniforms should be tryGet...
// because disabling fog can cause the GLSL to optimize out most (if not all) uniforms
this.gModelViewProjectionUniform = this.shader.tryGetUniformLocation("gMvmProj");
this.gDepthMapUniform = this.shader.tryGetUniformLocation("gDepthMap");
// Fog uniforms
fogColorUniform = this.shader.getUniformLocation("fogColor");
fullFogModeUniform = this.shader.getUniformLocation("fullFogMode");
fogScaleUniform = this.shader.tryGetUniformLocation("fogScale");
fogVerticalScaleUniform = this.shader.tryGetUniformLocation("fogVerticalScale");
// near
nearFogStartUniform = this.shader.tryGetUniformLocation("nearFogStart");
nearFogLengthUniform = this.shader.tryGetUniformLocation("nearFogLength");
this.fogColorUniform = this.shader.tryGetUniformLocation("fogColor");
this.fullFogModeUniform = this.shader.tryGetUniformLocation("fullFogMode");
this.fogScaleUniform = this.shader.tryGetUniformLocation("fogScale");
this.fogVerticalScaleUniform = this.shader.tryGetUniformLocation("fogVerticalScale");
// near fog
this.nearFogStartUniform = this.shader.tryGetUniformLocation("nearFogStart");
this.nearFogLengthUniform = this.shader.tryGetUniformLocation("nearFogLength");
}
@Override
void setVertexAttributes() {
va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
};
void setVertexAttributes()
{
this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
}
@Override
void setShaderUniforms(float partialTicks) {
void setShaderUniforms(float partialTicks)
{
this.shader.bind();
int lodDrawDistance = RenderUtil.getFarClipPlaneDistanceInBlocks();
int vanillaDrawDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
// super.bind();
vanillaDrawDistance += 32; // Give it a 2 chunk boundary for near fog.
Mat4f perspective = Mat4f.perspective(
(float) MC_RENDER.getFov(partialTicks),
MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(),
RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks),
(float) ((lodDrawDistance + LodUtil.REGION_WIDTH) * Math.sqrt(2)));
// if (worldYOffsetUniform != -1) this.shader.setUniform(worldYOffsetUniform, (float) MC.getWrappedClientWorld().getMinHeight());
this.shader.setUniform(this.shader.getUniformLocation("gProj"), perspective);
GL32.glUniform1i(gDepthMapUniform, 0);
vanillaDrawDistance += LodUtil.CHUNK_WIDTH * 2; // Give it a 2 chunk boundary for near fog.
// bind the depth buffer
if (this.gDepthMapUniform != -1)
{
GL32.glActiveTexture(GL32.GL_TEXTURE3);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
GL32.glUniform1i(this.gDepthMapUniform, 3);
}
// Fog
this.shader.setUniform(fullFogModeUniform, MC_RENDER.isFogStateSpecial() ? 1 : 0);
this.shader.setUniform(fogColorUniform, MC_RENDER.isFogStateSpecial() ? getSpecialFogColor(partialTicks) : getFogColor(partialTicks));
if (this.fullFogModeUniform != -1) this.shader.setUniform(this.fullFogModeUniform, MC_RENDER.isFogStateSpecial() ? 1 : 0);
if (this.fogColorUniform != -1) this.shader.setUniform(this.fogColorUniform, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks));
float nearFogLen = vanillaDrawDistance * 0.2f / lodDrawDistance;
float nearFogStart = vanillaDrawDistance * (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float)Math.sqrt(2.) : 1.f) / lodDrawDistance;
if (nearFogStartUniform != -1) this.shader.setUniform(nearFogStartUniform, nearFogStart);
if (nearFogLengthUniform != -1) this.shader.setUniform(nearFogLengthUniform, nearFogLen);
if (fogScaleUniform != -1) this.shader.setUniform(fogScaleUniform, 1.f/lodDrawDistance);
if (fogVerticalScaleUniform != -1) this.shader.setUniform(fogVerticalScaleUniform, 1.f/MC.getWrappedClientWorld().getHeight());
float nearFogStart = vanillaDrawDistance * (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float)Math.sqrt(2.0) : 1.0f) / lodDrawDistance;
if (this.nearFogStartUniform != -1) this.shader.setUniform(this.nearFogStartUniform, nearFogStart);
if (this.nearFogLengthUniform != -1) this.shader.setUniform(this.nearFogLengthUniform, nearFogLen);
if (this.fogScaleUniform != -1) this.shader.setUniform(this.fogScaleUniform, 1.f/lodDrawDistance);
if (this.fogVerticalScaleUniform != -1) this.shader.setUniform(this.fogVerticalScaleUniform, 1.f/MC.getWrappedClientWorld().getHeight());
}
@@ -105,18 +104,23 @@ public class FogShader extends AbstractShaderRenderer {
Color fogColor;
if (Config.Client.Advanced.Graphics.Fog.colorMode.get() == EFogColorMode.USE_SKY_COLOR)
fogColor = MC_RENDER.getSkyColor();
{
fogColor = MC_RENDER.getSkyColor();
}
else
fogColor = MC_RENDER.getFogColor(partialTicks);
{
fogColor = MC_RENDER.getFogColor(partialTicks);
}
return fogColor;
}
private Color getSpecialFogColor(float partialTicks)
{
return MC_RENDER.getSpecialFogColor(partialTicks);
}
private Color getSpecialFogColor(float partialTicks) { return MC_RENDER.getSpecialFogColor(partialTicks); }
public void setModelPos(Vec3f modelPos) {
// this.shader.setUniform(modelOffsetUniform, modelPos);
}
public void setModelViewProjectionMatrix(Mat4f combinedModelViewProjectionMatrix)
{
this.shader.bind();
this.shader.setUniform(this.gModelViewProjectionUniform, combinedModelViewProjectionMatrix);
this.shader.unbind();
}
}
@@ -172,23 +172,24 @@ public class SSAORenderer {
GL32.glUniform1i(ssaoShader.getUniformLocation("gDepthMap"), 0);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
applyShader.bind();
GL32.glEnable(GL11.GL_BLEND);
GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture);
GL32.glUniform1i(applyShader.getUniformLocation("gSSAOMap"), 0);
GL32.glActiveTexture(GL32.GL_TEXTURE1);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
GL32.glUniform1i(applyShader.getUniformLocation("gDepthMap"), 1);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
//GL32.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, ssaoFramebuffer);
//GL32.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
//GL32.glBlitFramebuffer(
// 0, 0, width, height,
// 0, 0, width, height,
// GL11.GL_COLOR_BUFFER_BIT,
// GL11.GL_NEAREST
//);
state.restore();
}
@@ -1,3 +1,4 @@
#version 150
in vec4 vertexColor;
in vec3 vertexWorldPos;
@@ -6,12 +7,6 @@ in vec4 vPos;
out vec4 fragColor;
// Fog Uniforms
uniform float fogScale;
uniform float fogVerticalScale;
uniform float nearFogStart;
uniform float nearFogLength;
uniform int fullFogMode;
// Noise Uniforms
uniform bool noiseEnabled;
@@ -19,32 +14,8 @@ uniform int noiseSteps;
uniform float noiseIntensity;
uniform int noiseDropoff;
/* ========MARCO DEFINED BY RUNTIME CODE GEN=========
float farFogStart;
float farFogLength;
float farFogMin;
float farFogRange;
float farFogDensity;
float heightFogStart;
float heightFogLength;
float heightFogMin;
float heightFogRange;
float heightFogDensity;
*/
uniform vec4 fogColor;
// method definitions
// ==== The below 5 methods will be run-time generated. ====
float getNearFogThickness(float dist);
float getFarFogThickness(float dist);
float getHeightFogThickness(float dist);
float calculateFarFogDepth(float horizontal, float dist, float nearFogStart);
float calculateHeightFogDepth(float vertical, float realY);
float mixFogThickness(float near, float far, float height);
// =========================================================
float fade(float value, float start, float end) {
return (clamp(value,start,end)-start)/(end-start);
@@ -97,7 +68,7 @@ vec3 HSV2RGB(vec3 c) {
void main()
{
fragColor = vertexColor;
// TODO: Move into its own function instead of in an if statement
if (noiseEnabled) {
@@ -155,30 +126,6 @@ void main()
// fragColor.w);
// }
}
// TODO: Move into its own function instead of in an if statement
// This is so that it can apply after the SSAO (work for this has started in the FogShader file and fog/fog.frag shader)
if (fullFogMode != 0) {
fragColor = vec4(fogColor.rgb, 1.0);
} else {
// TODO: add a white texture to support Optifine shaders
//vec4 textureColor = texture(texImage, textureCoord);
//fragColor = vertexColor * textureColor;
float horizontalDist = length(vertexWorldPos.xz) * fogScale;
float heightDist = calculateHeightFogDepth(
vertexWorldPos.y, vertexYPos) * fogVerticalScale;
float farDist = calculateFarFogDepth(horizontalDist,
length(vertexWorldPos.xyz) * fogScale, nearFogStart);
float nearFogThickness = getNearFogThickness(horizontalDist);
float farFogThickness = getFarFogThickness(farDist);
float heightFogThickness = getHeightFogThickness(heightDist);
float mixedFogThickness = clamp(mixFogThickness(
nearFogThickness, farFogThickness, heightFogThickness), 0.0, 1.0);
fragColor = mix(fragColor, vec4(fogColor.rgb, 1.0), mixedFogThickness);
}
}
+51 -38
View File
@@ -1,12 +1,11 @@
in vec2 TexCoord;
//in float vertexYPos;
out vec4 fragColor;
uniform sampler2D gDepthMap;
uniform mat4 gProj;
// model view matrix and projection matrix
uniform mat4 gMvmProj;
uniform float fogScale;
uniform float fogVerticalScale;
@@ -58,19 +57,18 @@ float mod(float x, int y) {
}
vec3 calcViewPosition(vec2 coords) {
float fragmentDepth = texture(gDepthMap, coords).r;
vec3 calcViewPosition(float fragmentDepth)
{
vec4 ndc = vec4(
coords.x * 2.0 - 1.0,
coords.y * 2.0 - 1.0,
TexCoord.x * 2.0 - 1.0,
TexCoord.y * 2.0 - 1.0,
fragmentDepth * 2.0 - 1.0,
1.0
);
vec4 vs_pos = inverse(gProj) * ndc;
vs_pos.xyz = vs_pos.xyz / vs_pos.w;
return vs_pos.xyz;
vec4 eyeCoord = inverse(gMvmProj) * ndc;
vec3 cameraPos = eyeCoord.xyz / eyeCoord.w;
return cameraPos;
}
/**
@@ -79,37 +77,52 @@ vec3 calcViewPosition(vec2 coords) {
*
* version: 2023-6-21
*/
void main() {
float vertexYPos = 100f;
vec3 vertexWorldPos = calcViewPosition(TexCoord);
void main()
{
float vertexYPos = 100.0f;
float fragmentDepth = texture(gDepthMap, TexCoord).r;
if (fullFogMode != 0) {
fragColor = vec4(fogColor.r, fogColor.g, fogColor.b, 1.);
} else {
float horizontalDist = length(vertexWorldPos.xz) * fogScale;
float heightDist = calculateHeightFogDepth(
vertexWorldPos.y, vertexYPos) * fogVerticalScale;
float farDist = calculateFarFogDepth(horizontalDist,
length(vertexWorldPos.xyz) * fogScale, nearFogStart);
// a fragment depth of "1" means the fragment wasn't drawn to,
// we only want to apply Fog to LODs, not to the sky outside the LODs
if (fragmentDepth != 1.0)
{
if (fullFogMode == 0)
{
// render fog based on distance from the camera
vec3 vertexWorldPos = calcViewPosition(fragmentDepth);
float nearFogThickness = getNearFogThickness(horizontalDist);
float farFogThickness = getFarFogThickness(farDist);
float heightFogThickness = getHeightFogThickness(heightDist);
float mixedFogThickness = clamp(mixFogThickness(
nearFogThickness, farFogThickness, heightFogThickness), 0.0, 1.0);
float horizontalDist = length(vertexWorldPos.xz) * fogScale;
float heightDist = calculateHeightFogDepth(vertexWorldPos.y, vertexYPos) * fogVerticalScale;
float farDist = calculateFarFogDepth(horizontalDist, length(vertexWorldPos.xyz) * fogScale, nearFogStart);
fragColor = vec4(fogColor.r, fogColor.g, fogColor.b, mixedFogThickness);
float nearFogThickness = getNearFogThickness(horizontalDist);
float farFogThickness = getFarFogThickness(farDist);
float heightFogThickness = getHeightFogThickness(heightDist);
float mixedFogThickness =
clamp(
mixFogThickness(nearFogThickness, farFogThickness, heightFogThickness)
, 0.0, 1.0);
fragColor = vec4(fogColor.r, fogColor.g, fogColor.b, mixedFogThickness);
}
else if (fullFogMode == 1)
{
// render everything with the fog color
fragColor = vec4(fogColor.r, fogColor.g, fogColor.b, 1.0);
}
else
{
// test code.
// this can be fired by manually changing the fullFogMode to a (normally)
// invalid value (like 7). By having a separate if statement defined by
// a uniform we don't have to worry about GLSL optimizing away different
// options when testing, causing a bunch of headaches if we just want to render the screen red.
float depthValue = texture(gDepthMap, TexCoord).r;
fragColor = vec4(vec3(depthValue), 1.0); // Convert depth value to grayscale color
}
}
// Testing
// if (fragColor.r != 6969.) { // This line is so that the compiler doesnt delete the previos code
// fragColor = vec4(
// mod(texture(gDepthMap, TexCoord).x, 1),
// mod(texture(gDepthMap, TexCoord).y, 1),
// mod(texture(gDepthMap, TexCoord).z, 1),
// 1.
// );
// }
}
@@ -6,8 +6,15 @@ in vec2 ViewRay;
out vec4 fragColor;
uniform sampler2D gSSAOMap;
uniform sampler2D gDepthMap;
void main()
{
fragColor = vec4(0.0, 0.0, 0.0, 1-texture(gSSAOMap, TexCoord).r);
}
float fragmentDepth = texture(gDepthMap, TexCoord).r;
// a fragment depth of "1" means the fragment wasn't drawn to,
// we only want to apply SSAO to LODs, not to the sky outside the LODs
if (fragmentDepth != 1.0)
{
fragColor = vec4(0.0, 0.0, 0.0, 1-texture(gSSAOMap, TexCoord).r);
}
}
@@ -55,7 +55,9 @@ void main()
float light = (float(lights/16u)+0.5) / 16.0;
vertexColor = vec4(texture(lightMap, vec2(light, light2)).xyz, 1.0);
if (!whiteWorld)
{
vertexColor *= color;
}
gl_Position = combinedMatrix * vec4(vertexWorldPos + vec3(mx, 0, mz), 1.0);
}