Improve dithering quality

This commit is contained in:
James Seibel
2024-10-02 07:35:32 -05:00
parent fbaff8d850
commit 85c00e50d9
4 changed files with 21 additions and 17 deletions
@@ -196,10 +196,8 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
// Clip Uniform
float dhNearClipDistance = RenderUtil.getNearClipPlaneDistanceInBlocks(renderParameters.partialTicks);
// TODO a different multiplier might be necessary
// this is to try and allow the fragment culling to go farther than the near clip plane.
// Currently this only works for certain FOV/screen ratio combos.
dhNearClipDistance *= 2.0f;
// this added value prevents the near clip plane and discard circle from touching, which looks bad
dhNearClipDistance += 16f;
// if the player is very high up and the near clip plane has been modified, disable the distance clipping
// we're high enough that nothing will render on top of the player and this can cause issues otherwise
if (RenderUtil.getHeightBasedNearClipOverride() != -1)
@@ -110,10 +110,15 @@ public class FadeShader extends AbstractShaderRenderer
if (this.inverseDhMvmProjMatrix != null) this.shader.setUniform(this.uDhInvMvmProj, this.inverseDhMvmProjMatrix);
int vanillaBlockRenderDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
float dhNearClipDistance = RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks);
// this added value prevents the near clip plane and discard circle from touching, which looks bad
dhNearClipDistance += 16f;
// measured in blocks
float fadeStartDistance = vanillaBlockRenderDistance * 0.5f;
float fadeEndDistance = vanillaBlockRenderDistance * 0.8f;
// these multipliers in James' tests should provide a fairly smooth transition
// without having underdraw issues
float fadeStartDistance = dhNearClipDistance * 1.5f;
float fadeEndDistance = dhNearClipDistance * 1.9f;
if (this.uStartFadeBlockDistance != -1) this.shader.setUniform(this.uStartFadeBlockDistance, fadeStartDistance);
if (this.uEndFadeBlockDistance != -1) this.shader.setUniform(this.uEndFadeBlockDistance, fadeEndDistance);
@@ -114,7 +114,7 @@ public class RenderUtil
// modify based on the player's FOV
double fov = MC_RENDER.getFov(partialTicks);
double aspectRatio = (double) MC_RENDER.getScreenWidth() / MC_RENDER.getScreenHeight();
double aspectRatio = (double) MC_RENDER.getTargetFrameBufferViewportWidth() / MC_RENDER.getTargetFrameBufferViewportHeight();
// source: https://stackoverflow.com/questions/8101119/how-do-i-methodically-choose-the-near-clip-plane-distance-for-a-perspective-proj/8101234#8101234
return (float) (nearClipPlane
@@ -61,9 +61,8 @@ 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);
}
float worldPosToNoise(vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453); }
void main()
@@ -74,18 +73,20 @@ void main()
if (uDitherDhRendering)
{
// only for opaque pass //
// Dither out the fragment based on distance and noise.
float noiseValue = random(vertexWorldPos.xy);
// Dithering is used since it works for both opaque and transparent rendering
// noise increases as the distance increases
float worldNoise = worldPosToNoise(vertexWorldPos.xy);
float fadeStep = smoothstep(uClipDistance, uClipDistance * 1.5, viewDist);
if (fadeStep < noiseValue)
if (fadeStep < worldNoise)
{
discard; // Discard if the fadeStep is less than the noise.
discard;
}
// only for transparent pass //
// this logic could be used for transparent rendering,
// however we don't currently have the logic needed to differentiate opaque/transparenet rendering
//float fadeStep = smoothstep(uClipDistance, uClipDistance * 2, viewDist);
//fragColor.a = min(fadeStep, fragColor.a);
}