diff options
| author | Adam Malczewski <[email protected]> | 2026-06-14 13:34:04 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-14 13:34:04 +0900 |
| commit | 4e0b07cecd1dc5cbd4fcabe05cbcfc897ce6dc43 (patch) | |
| tree | e33ab068f9c6840a0dc180de676d961d0110840a | |
| parent | 18bcca4f820aca68c6f50c4d59b66d73f0d0970d (diff) | |
| download | unbox-4e0b07cecd1dc5cbd4fcabe05cbcfc897ce6dc43.tar.gz unbox-4e0b07cecd1dc5cbd4fcabe05cbcfc897ce6dc43.zip | |
kernel: dither gradient shader to kill 8-bit banding (TPDF ~1 LSB)
The shader-based gradient (linear/radial) fragment shader now adds a
mean-zero triangular-PDF dither (~1 LSB of 8-bit) from a spatial pixel-position
hash before writing finalColor, so smooth ramps (e.g. an alpha fade) no longer
show quantization banding when written to the 8-bit surface buffer. Spatial,
non-temporal — no shimmer on static panels. Applies to every shader gradient.
| -rw-r--r-- | packages/kernel/src/rmlui_renderer_gl3.cpp | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/packages/kernel/src/rmlui_renderer_gl3.cpp b/packages/kernel/src/rmlui_renderer_gl3.cpp index dfb455f..092c1c8 100644 --- a/packages/kernel/src/rmlui_renderer_gl3.cpp +++ b/packages/kernel/src/rmlui_renderer_gl3.cpp @@ -128,6 +128,13 @@ in vec2 fragTexCoord; in vec4 fragColor; out vec4 finalColor; +// Dave Hoskins' hash (https://www.shadertoy.com/view/4djSRW): vec2 -> [0,1). +float hash12(vec2 p) { + vec3 q = fract(vec3(p.xyx) * 0.1031); + q += dot(q, q.yzx + 33.33); + return fract((q.x + q.y) * q.z); +} + vec4 mix_stop_colors(float t) { vec4 color = _stop_colors[0]; @@ -165,7 +172,14 @@ void main() { t = t0 + mod(t - t0, t1 - t0); } - finalColor = fragColor * mix_stop_colors(t); + vec4 color = fragColor * mix_stop_colors(t); + // TPDF (triangular-PDF) dither, ~1 LSB of 8-bit, applied before this color is + // written to the 8-bit surface buffer — breaks the quantization banding of a + // smooth gradient (e.g. the dock's alpha ramp). Mean-zero, so it does not + // shift the gradient; spatial pixel-position hash (no texture) and NON-temporal + // so a mostly-static panel does not shimmer frame to frame. + float dither = (hash12(gl_FragCoord.xy) - hash12(gl_FragCoord.xy + 37.0)) / 255.0; + finalColor = color + dither; } )"; |
