Reputation: 1353
I'm using the following shader to render a skydome to simulate a night sky. My issue is the clearly visible transitions between colours.
What causes these harsh gradient transitions?
Fragment shader:
#version 330
in vec3 worldPosition;
layout(location = 0) out vec4 outputColor;
void main()
{
float height = 0.007*(abs(worldPosition.y)-200);
vec4 apexColor = vec4(0,0,0,1);
vec4 centerColor = vec4(0.159, 0.132, 0.1, 1);
outputColor = mix(centerColor, apexColor, height);
}
Fbo pixel format:
GL.TexImage2D(
TextureTarget.Texture2D,
0,
PixelInternalFormat.Rgb32f,
WindowWidth,
WindowHeight,
0,
PixelFormat.Rgb,
PixelType.Float,
IntPtr.Zero )
Upvotes: 6
Views: 1899
Reputation: 1353
As Ripi2 explained, 24 bit color is unable to perfectly represent a gradient and discontinuities between representable colours become jarringly visible on gradients of a single color.
To hide the color banding I implemented a simple form of ordered dithering with an 8x8 texture generated using this bayer matrix algorithm.
vec4 dither = vec4(texture2D(MyTexture0, gl_FragCoord.xy / 8.0).r / 32.0 - (1.0 / 128.0));
colourOut += dither;
Upvotes: 8
Reputation: 7198
Normally monitors have 8 bits per channel of resolution. For example, the red intensity varies from 0 to 255.
If your window horizontal size is 768 pixels and you want a full gradient on red channel, then each color step takes 768/256 = 3 pixels. Depending on your eye health you may see bands.
How to do smooth gradient on those 3 pixels? Use sub-pixel rendering.
Basically you "expand" the color step among the neighbour pixels: Add small amounts of other channels to neighbours, and reduce a bit the central pixel amount.
Upvotes: 2