From 89edd1878791a77256e170a79c7cf9ecc9f649d8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 28 Jan 2022 22:55:38 -0500 Subject: [PATCH] Dither in nonlinear srgb space and add a few dithering related things to the experimental shader options --- assets/voxygen/shaders/include/random.glsl | 10 ++++++++++ assets/voxygen/shaders/postprocess-frag.glsl | 21 ++++++++++++++++++-- voxygen/src/render/mod.rs | 6 ++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index a3ce9c8137..4330ca3770 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -109,4 +109,14 @@ vec3 smooth_rand(vec3 pos, float lerp_axis) { vec3 r1 = rand_perm_3(vec3(pos.x, pos.y, pos.z) + floor(lerp_axis + 1.0)); return r0 + (r1 - r0) * fract(lerp_axis); } + +// Transform normal distribution to triangle distribution. +float norm2tri(float n) { + // TODO: compare perf with adding two normal noise distributions + bool flip = n > 0.5; + n = flip ? 1.0 - n : n; + n = sqrt(n / 2.0); + n = flip ? 1.0 - n : n; + return n; +} #endif diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 8882f42faf..50059e245c 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -282,9 +282,26 @@ void main() { } #endif +#ifndef EXPERIMENTAL_NODITHER // Add a small amount of very cheap dithering noise to remove banding from gradients - // TODO: Instead of 256, detect the colour resolution of the display - final_color.rgb = max(vec3(0), final_color.rgb - hash_two(uvec2(uv * screen_res.xy)) / 256.0); + // TODO: Consider dithering each color channel independently. + // TODO: Consider varying dither over time. + // TODO: Instead of 255, detect the colour resolution of the color attachment + float noise = hash_two(uvec2(uv * screen_res.xy)); + #ifndef EXPERIMENTAL_NONSRGBDITHER + #ifndef EXPERIMENTAL_TRIANGLENOISEDITHER + noise = noise - 0.5; + #else + // TODO: there is something special we have to do to remove bias + // on the bounds when using triangle distribution + noise = 2.0 * norm2tri(noise) - 1.0; + #endif + final_color.rgb = srgb_to_linear(linear_to_srgb(final_color.rgb) + noise / 255.0); + #else + // NOTE: GPU will clamp value + final_color.rgb = final_color.rgb - noise / 255.0; + #endif +#endif tgt_color = vec4(final_color.rgb, 1); } diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index e5066f374f..3da8c2f4d8 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -447,4 +447,10 @@ pub enum ExperimentalShader { Underwarper, /// Remove caustics from underwater terrain when shiny water is enabled. NoCaustics, + /// Don't dither color in post-processing. + NoDither, + /// Don't use the nonlinear srgb space for dithering color. + NonSrgbDither, + /// Use triangle PDF noise for dithering instead of uniform noise. + TriangleNoiseDither, }