Add dithered DH fading, double pass fading, and fix LOD clouds

This commit is contained in:
James Seibel
2024-10-01 22:02:32 -05:00
parent 72607a4fc9
commit fbaff8d850
9 changed files with 141 additions and 47 deletions
@@ -24,6 +24,7 @@ import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
import com.seibel.distanthorizons.core.level.DhClientLevel;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
import com.seibel.distanthorizons.core.render.renderer.FadeRenderer;
@@ -552,11 +553,20 @@ public class ClientApi
}
/** should be called after DH and MC finish rendering so we can smooth the transition between the two */
public void renderFade(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks)
public void renderFadeOpaque(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IClientLevelWrapper level)
{
if (Config.Client.Advanced.Graphics.Quality.fadeOutVanillaRendering.get()
&& Config.Client.Advanced.Graphics.Quality.twoPassVanillaFade.get())
{
FadeRenderer.INSTANCE.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, level);
}
}
/** should be called after DH and MC finish rendering so we can smooth the transition between the two */
public void renderFade(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IClientLevelWrapper level)
{
if (Config.Client.Advanced.Graphics.Quality.fadeOutVanillaRendering.get())
{
FadeRenderer.INSTANCE.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks);
FadeRenderer.INSTANCE.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, level);
}
}
@@ -262,7 +262,22 @@ public class Config
+ "smoothing the transition between Distant Horizons and vanilla rendering. \n"
+ "")
.setPerformance(EConfigEntryPerformance.LOW)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry<Boolean> twoPassVanillaFade = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "TODO \n"
+ "")
.setPerformance(EConfigEntryPerformance.LOW)
.build();
public static ConfigEntry<Boolean> ditherDhFade = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "TODO \n"
+ "")
.setPerformance(EConfigEntryPerformance.LOW)
.build();
// TODO fixme
@@ -43,27 +43,28 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
public final AbstractVertexAttribute vao;
// Uniforms
public final int uCombinedMatrix;
public final int uModelOffset;
public final int uWorldYOffset;
public int uCombinedMatrix = -1;
public int uModelOffset = -1;
public int uWorldYOffset = -1;
public int uDitherDhRendering = -1;
public final int uMircoOffset;
public int uMircoOffset = -1;
public final int uEarthRadius;
public int uEarthRadius = -1;
public final int uLightMap;
public int uLightMap = -1;
// Fog/Clip Uniforms
public final int uClipDistance;
public int uClipDistance = -1;
// Noise Uniforms
public final int uNoiseEnabled;
public final int uNoiseSteps;
public final int uNoiseIntensity;
public final int uNoiseDropoff;
public int uNoiseEnabled = -1;
public int uNoiseSteps = -1;
public int uNoiseIntensity = -1;
public int uNoiseDropoff = -1;
// Debug Uniform
public final int uWhiteWorld;
public int uWhiteWorld = -1;
@@ -85,6 +86,7 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
this.uCombinedMatrix = this.getUniformLocation("uCombinedMatrix");
this.uModelOffset = this.getUniformLocation("uModelOffset");
this.uWorldYOffset = this.tryGetUniformLocation("uWorldYOffset");
this.uDitherDhRendering = this.tryGetUniformLocation("uDitherDhRendering");
this.uMircoOffset = this.getUniformLocation("uMircoOffset");
this.uEarthRadius = this.tryGetUniformLocation("uEarthRadius");
@@ -187,6 +189,8 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
if (this.uWorldYOffset != -1) this.setUniform(this.uWorldYOffset, (float) renderParameters.worldYOffset);
if (this.uDitherDhRendering != -1) this.setUniform(this.uDitherDhRendering, Config.Client.Advanced.Graphics.Quality.ditherDhFade.get());
// Debug
this.setUniform(this.uWhiteWorld, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.core.render.renderer;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.level.DhClientLevel;
import com.seibel.distanthorizons.core.render.glObject.GLState;
import com.seibel.distanthorizons.core.render.renderer.shaders.FadeApplyShader;
import com.seibel.distanthorizons.core.render.renderer.shaders.FadeShader;
@@ -27,6 +28,7 @@ import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.opengl.GL32;
@@ -106,7 +108,7 @@ public class FadeRenderer
// render //
//========//
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks)
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IClientLevelWrapper level)
{
IProfilerWrapper profiler = MC_CLIENT.getProfiler();
profiler.pop(); // get out of "terrain"
@@ -134,7 +136,8 @@ public class FadeRenderer
FadeShader.INSTANCE.frameBuffer = this.fadeFramebuffer;
FadeShader.INSTANCE.setProjectionMatrix(mcModelViewMatrix, mcProjectionMatrix);
FadeShader.INSTANCE.setProjectionMatrix(mcModelViewMatrix, mcProjectionMatrix, partialTicks);
FadeShader.INSTANCE.setLevelMaxHeight(level.getMaxHeight());
FadeShader.INSTANCE.render(partialTicks);
// restored so we can write the fade texture to the main frame buffer
@@ -101,9 +101,7 @@ public class FadeApplyShader extends AbstractShaderRenderer
@Override
protected void onRender()
{
GL32.glEnable(GL32.GL_BLEND);
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
GL32.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
GL32.glDisable(GL32.GL_BLEND);
// Depth testing must be disabled otherwise this application shader won't apply anything.
// setting this isn't necessary in vanilla, but some mods may change this, requiring it to be set manually,
@@ -25,6 +25,7 @@ import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
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.util.math.Mat4f;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
@@ -40,20 +41,26 @@ public class FadeShader extends AbstractShaderRenderer
public int frameBuffer = -1;
private Mat4f inverseMvmProjMatrix;
private Mat4f inverseMcMvmProjMatrix;
private Mat4f inverseDhMvmProjMatrix;
private float levelMaxHeight;
// Uniforms
public int uMcDepthTexture = -1;
public int uDhDepthTexture = -1;
public int uCombinedMcDhColorTexture = -1;
public int uDhColorTexture = -1;
/** Inverted Model View Projection matrix */
public int uInvMvmProj = -1;
public int uDhInvMvmProj = -1;
public int uMcInvMvmProj = -1;
public int uStartFadeBlockDistance = -1;
public int uEndFadeBlockDistance = -1;
public int uMaxLevelHeight = -1;
@@ -75,15 +82,19 @@ public class FadeShader extends AbstractShaderRenderer
// because disabling fade can cause the GLSL to optimize out most (if not all) uniforms
// near fade
this.uInvMvmProj = this.shader.tryGetUniformLocation("uInvMvmProj");
this.uDhInvMvmProj = this.shader.tryGetUniformLocation("uDhInvMvmProj");
this.uMcInvMvmProj = this.shader.tryGetUniformLocation("uMcInvMvmProj");
this.uMcDepthTexture = this.shader.tryGetUniformLocation("uMcDepthMap");
this.uDhDepthTexture = this.shader.tryGetUniformLocation("uDhDepthTexture");
this.uCombinedMcDhColorTexture = this.shader.tryGetUniformLocation("uCombinedMcDhColorTexture");
this.uDhColorTexture = this.shader.tryGetUniformLocation("uDhColorTexture");
this.uStartFadeBlockDistance = this.shader.tryGetUniformLocation("uStartFadeBlockDistance");
this.uEndFadeBlockDistance = this.shader.tryGetUniformLocation("uEndFadeBlockDistance");
this.uMaxLevelHeight = this.shader.tryGetUniformLocation("uMaxLevelHeight");
}
@@ -95,10 +106,8 @@ public class FadeShader extends AbstractShaderRenderer
@Override
protected void onApplyUniforms(float partialTicks)
{
if (this.inverseMvmProjMatrix != null)
{
this.shader.setUniform(this.uInvMvmProj, this.inverseMvmProjMatrix);
}
if (this.inverseMcMvmProjMatrix != null) this.shader.setUniform(this.uMcInvMvmProj, this.inverseMcMvmProjMatrix);
if (this.inverseDhMvmProjMatrix != null) this.shader.setUniform(this.uDhInvMvmProj, this.inverseDhMvmProjMatrix);
int vanillaBlockRenderDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
@@ -108,16 +117,27 @@ public class FadeShader extends AbstractShaderRenderer
if (this.uStartFadeBlockDistance != -1) this.shader.setUniform(this.uStartFadeBlockDistance, fadeStartDistance);
if (this.uEndFadeBlockDistance != -1) this.shader.setUniform(this.uEndFadeBlockDistance, fadeEndDistance);
if (this.uMaxLevelHeight != -1) this.shader.setUniform(this.uMaxLevelHeight, this.levelMaxHeight);
}
public void setProjectionMatrix(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix)
public void setProjectionMatrix(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks)
{
Mat4f inverseModelViewProjectionMatrix = new Mat4f(mcProjectionMatrix);
inverseModelViewProjectionMatrix.multiply(mcModelViewMatrix);
inverseModelViewProjectionMatrix.invert();
Mat4f inverseMcModelViewProjectionMatrix = new Mat4f(mcProjectionMatrix);
inverseMcModelViewProjectionMatrix.multiply(mcModelViewMatrix);
inverseMcModelViewProjectionMatrix.invert();
this.inverseMcMvmProjMatrix = inverseMcModelViewProjectionMatrix;
this.inverseMvmProjMatrix = inverseModelViewProjectionMatrix;
Mat4f dhProjectionMatrix = RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks);
Mat4f dhModelViewMatrix = RenderUtil.createLodModelViewMatrix(mcModelViewMatrix);
Mat4f inverseDhModelViewProjectionMatrix = new Mat4f(dhProjectionMatrix);
inverseDhModelViewProjectionMatrix.multiply(dhModelViewMatrix);
inverseDhModelViewProjectionMatrix.invert();
this.inverseDhMvmProjMatrix = inverseDhModelViewProjectionMatrix;
}
public void setLevelMaxHeight(int levelMaxHeight) { this.levelMaxHeight = levelMaxHeight; }
@@ -140,12 +160,16 @@ public class FadeShader extends AbstractShaderRenderer
GL32.glUniform1i(this.uMcDepthTexture, 0);
GL32.glActiveTexture(GL32.GL_TEXTURE1);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getColorTextureId());
GL32.glUniform1i(this.uCombinedMcDhColorTexture, 1);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveDepthTextureId());
GL32.glUniform1i(this.uDhDepthTexture, 1);
GL32.glActiveTexture(GL32.GL_TEXTURE2);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getColorTextureId());
GL32.glUniform1i(this.uCombinedMcDhColorTexture, 2);
GL32.glActiveTexture(GL32.GL_TEXTURE3);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveColorTextureId());
GL32.glUniform1i(this.uDhColorTexture, 2);
GL32.glUniform1i(this.uDhColorTexture, 3);
// this is necessary for MC 1.16 (IE Legacy OpenGL)
// otherwise the framebuffer isn't cleared correctly and the fade smears across the screen
@@ -118,6 +118,12 @@
"Fade Out Vanilla Rendering",
"distanthorizons.config.client.advanced.graphics.quality.fadeOutVanillaRendering.@tooltip":
"If true vanilla chunks will fade out the further away they are\nsmoothing the transition between Distant Horizons and vanilla rendering.",
"distanthorizons.config.client.advanced.graphics.quality.twoPassVanillaFade":
"Two Pass Vanilla Fade",
"distanthorizons.config.client.advanced.graphics.quality.ditherDhFade":
"Dither DH Near Rendering",
"distanthorizons.config.client.advanced.graphics.quality.lodBiomeBlending":
"Biome Blending",
"distanthorizons.config.client.advanced.graphics.quality.lodBiomeBlending.@tooltip":
+18 -9
View File
@@ -5,23 +5,26 @@ in vec2 TexCoord;
out vec4 fragColor;
uniform sampler2D uMcDepthTexture;
uniform sampler2D uDhDepthTexture;
uniform sampler2D uCombinedMcDhColorTexture;
uniform sampler2D uDhColorTexture;
// inverted model view matrix and projection matrix
uniform mat4 uInvMvmProj;
uniform mat4 uDhInvMvmProj;
uniform mat4 uMcInvMvmProj;
uniform float uStartFadeBlockDistance;
uniform float uEndFadeBlockDistance;
uniform float uMaxLevelHeight;
vec3 calcViewPosition(float fragmentDepth)
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
{
// normalized device coordinates
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
ndc.xyz = ndc.xyz * 2.0 - 1.0;
vec4 eyeCoord = uInvMvmProj * ndc;
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
@@ -44,21 +47,27 @@ void main()
dhColor = combinedMcDhColor;
}
float mcFragmentDepth = texture(uMcDepthTexture, TexCoord).r;
float dhFragmentDepth = texture(uDhDepthTexture, TexCoord).r;
vec3 dhVertexWorldPos = calcViewPosition(dhFragmentDepth, uDhInvMvmProj);
// this is a work around to prevent MC clouds rendering behind DH clouds
if (dhVertexWorldPos.y > uMaxLevelHeight)
{
fragColor = vec4(combinedMcDhColor.rgb, 0.0);
}
// a fragment depth of "1" means the fragment wasn't drawn to,
// we only want to fade vanilla rendered objects, not to the sky or LODs
float mcFragmentDepth = texture(uMcDepthTexture, TexCoord).r;
if (mcFragmentDepth < 1.0)
else if (mcFragmentDepth < 1.0)
{
// fade based on distance from the camera
vec3 vertexWorldPos = calcViewPosition(mcFragmentDepth);
float fragmentDistance = length(vertexWorldPos.xzy);
vec3 mcVertexWorldPos = calcViewPosition(mcFragmentDepth, uMcInvMvmProj);
float mcFragmentDistance = length(mcVertexWorldPos.xzy);
// Smoothly transition between combinedMcDhColor and uDhColorTexture
// as the depth increases from the camera
float fadeStep = smoothstep(uStartFadeBlockDistance, uEndFadeBlockDistance, fragmentDistance);
float fadeStep = smoothstep(uStartFadeBlockDistance, uEndFadeBlockDistance, mcFragmentDistance);
fragColor = mix(combinedMcDhColor, dhColor, fadeStep);
fragColor.a = 1.0; // TODO is setting the alpha needed?
}
@@ -16,6 +16,7 @@ uniform bool uNoiseEnabled;
uniform int uNoiseSteps;
uniform float uNoiseIntensity;
uniform int uNoiseDropoff;
uniform bool uDitherDhRendering;
// The random functions for diffrent dimentions
@@ -60,16 +61,40 @@ void applyNoise(inout vec4 fragColor, const in float viewDist)
fragColor.rgb = newCol;
}
float random(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
void main()
{
fragColor = vertexColor;
float viewDist = length(vertexWorldPos);
if (viewDist < uClipDistance && uClipDistance > 0.0)
if (uDitherDhRendering)
{
discard;
// only for opaque pass //
// Dither out the fragment based on distance and noise.
float noiseValue = random(vertexWorldPos.xy);
float fadeStep = smoothstep(uClipDistance, uClipDistance * 1.5, viewDist);
if (fadeStep < noiseValue)
{
discard; // Discard if the fadeStep is less than the noise.
}
// only for transparent pass //
//float fadeStep = smoothstep(uClipDistance, uClipDistance * 2, viewDist);
//fragColor.a = min(fadeStep, fragColor.a);
}
else
{
if (viewDist < uClipDistance && uClipDistance > 0.0)
{
discard;
}
}
if (uNoiseEnabled)