From 4ecff488f166c797941011ba4ee1ab012d076175 Mon Sep 17 00:00:00 2001 From: Ruffled <105522716+RuffledPlume@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:38:18 +0000 Subject: [PATCH] Dither out geom that is about the clip with the near plane --- src/main/resources/rs117/hd/scene_frag.glsl | 14 ++++++++++++++ src/main/resources/rs117/hd/scene_vert.glsl | 9 +++++---- src/main/resources/rs117/hd/utils/misc.glsl | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/main/resources/rs117/hd/scene_frag.glsl b/src/main/resources/rs117/hd/scene_frag.glsl index bcc9ac06f0..f43ebd92c2 100644 --- a/src/main/resources/rs117/hd/scene_frag.glsl +++ b/src/main/resources/rs117/hd/scene_frag.glsl @@ -32,6 +32,8 @@ #define DISPLAY_SHADOWS 0 #define DISPLAY_LIGHTING 0 +#define NEAR_PLANE_DITHER_START 0.2 + #include #include #include @@ -55,6 +57,9 @@ flat in ivec3 fTerrainData; #endif in FragmentData { +#if ZONE_RENDERER + vec4 positionCS; +#endif vec3 position; vec2 uv; vec3 normal; @@ -84,6 +89,15 @@ vec2 worldUvs(float scale) { void main() { vec3 downDir = vec3(0, -1, 0); +#if ZONE_RENDERER + float viewZ = 1.0 - (0.5 + (IN.positionCS.z / IN.positionCS.w) * 0.5); + if(viewZ < NEAR_PLANE_DITHER_START) { + float fadeAmount = 1.0 - saturate(viewZ / NEAR_PLANE_DITHER_START); + if(orderedDither(gl_FragCoord.xy, pow(fadeAmount, 1.5) - 0.01, 1.75)) + discard; + } +#endif + // View & light directions are from the fragment to the camera/light vec3 viewDir = normalize(cameraPos - IN.position); diff --git a/src/main/resources/rs117/hd/scene_vert.glsl b/src/main/resources/rs117/hd/scene_vert.glsl index 06b5268582..725ca0d4e5 100644 --- a/src/main/resources/rs117/hd/scene_vert.glsl +++ b/src/main/resources/rs117/hd/scene_vert.glsl @@ -60,6 +60,7 @@ layout (location = 0) in vec3 vPosition; #endif out FragmentData { + vec4 positionCS; vec3 position; vec2 uv; vec3 normal; @@ -109,12 +110,12 @@ layout (location = 0) in vec3 vPosition; fFlatNormal = worldNormal; #endif - vec4 clipPosition = projectionMatrix * vec4(worldPosition, 1.0); int depthBias = (alphaBiasHsl >> 16) & 0xff; - if (projectionMatrix[2][3] != 0) // Disable depth bias for orthographic projection - clipPosition.z += depthBias / 128.0; + OUT.positionCS = projectionMatrix * vec4(worldPosition, 1.0); + if (projectionMatrix[2][3] != 0) // Disable depth bias for orthographic projection + OUT.positionCS.z += depthBias / 128.0; - gl_Position = clipPosition; + gl_Position = OUT.positionCS; } #else out vec3 gPosition; diff --git a/src/main/resources/rs117/hd/utils/misc.glsl b/src/main/resources/rs117/hd/utils/misc.glsl index 6e5406693b..b194fcff9c 100644 --- a/src/main/resources/rs117/hd/utils/misc.glsl +++ b/src/main/resources/rs117/hd/utils/misc.glsl @@ -112,6 +112,25 @@ void undoVanillaShading(inout int hsl, vec3 unrotatedNormal) { } #endif +const int DITHER_MAP_LEN = 4; +const float DITHER_MAP_SCALE = 16.0; + +const float DITHER_MAP[DITHER_MAP_LEN * DITHER_MAP_LEN] = float[]( + 0.0 / DITHER_MAP_SCALE, 8.0 / DITHER_MAP_SCALE, 2.0 / DITHER_MAP_SCALE, 10.0 / DITHER_MAP_SCALE, + 12.0 / DITHER_MAP_SCALE, 4.0 / DITHER_MAP_SCALE, 14.0 / DITHER_MAP_SCALE, 6.0 / DITHER_MAP_SCALE, + 3.0 / DITHER_MAP_SCALE, 11.0 / DITHER_MAP_SCALE, 1.0 / DITHER_MAP_SCALE, 9.0 / DITHER_MAP_SCALE, + 15.0 / DITHER_MAP_SCALE, 7.0 / DITHER_MAP_SCALE, 13.0 / DITHER_MAP_SCALE, 5.0 / DITHER_MAP_SCALE +); + +// ------------------------------------------------------------ +// Based on https://www.shadertoy.com/view/4t2cRt +// Returns a dither value (0.0 or 1.0) based on coords + opacity +// ------------------------------------------------------------ +bool orderedDither(vec2 pixelCoord, float opacity, float scaleFactor) { + ivec2 coord = ivec2(pixelCoord / scaleFactor) & (DITHER_MAP_LEN - 1); + return DITHER_MAP[coord.x + coord.y * DITHER_MAP_LEN] < clamp(opacity, 0.0, 1.0); +} + // 2D Random float hash(in vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);