While working on shadow mapping I've been investigating dithering and its applications. It was mainly used back in the day to display high bit depth images in low bit depth displays, although it can still be used today for that same thing. The skydome suffers from banding because the framebuffer only has a bit depth of 8 per color, while floats in the shader have a much higher resolution, so some loss of precision is happening. This can be prevented by randomly rounding up and down to the next available color in the display. The random factor used can be as simple as a one-liner noise function or some fancy blue noise texture. I just used the rand2D() from Thorsten's noise functions as it outputs a good enough result.
This could be done as a post-processing effect so it affects every object in the scene, but banding is mostly perceived only on the skydome, so this is a good enough fix for now.
Before:
After:
And the code to add just before gl_FragColor and after filter_combined() in skydome-ALS.frag:
- Code: Select all
float dither_noise = rand2D(gl_FragCoord.xy);
color += mix(-0.5/255.0, 0.5/255.0, dither_noise);