diffuse shader color bands

All,

The following shaders render geometry with color bands, see the image below. Why is this happening?

Thank you,
Robert

/** transforms [0, 0, 0, 1] to the light position in eye coordinates */
uniform mat4 lightMatrix;

/**
* @author Robert MacHardy
* a diffuse vertex shader
*/
void main()
{
	gl_Position = ftransform();
	
	vec4 vertexEye = gl_ModelViewMatrix * gl_Vertex;
	vec4 lightPosEye = lightMatrix * vec4(0, 0, 0, 1);
	vec3 lightNormal = normalize(lightPosEye.xyz - vertexEye.xyz);
	vec3 normalEye = (gl_NormalMatrix * gl_Normal) / gl_NormalScale;
	
	gl_FrontColor.rgb = vec3(max(dot(lightNormal, normalEye), 0));
	gl_FrontColor.a = 1;
}
/**
* @author Robert MacHardy
* a diffuse fragment shader
*/
void main(void)
{
	gl_FragColor = gl_Color;
}

All,

It “appears” my image is not always retrieved from the server.

Here it is again, twice.

Thank you,
Robert

Why is this happening?

This is likely because the framebuffer only has 16-bits per pixel accuracy. Increase to a 32-bit framebuffer to compensate.

I am using a 32 bit framebuffer. Also, I have written other shaders where color interpolation between vertices does not appear banded.

Thank you,
Robert

Some calculations just don’t work well when interpolating the results of a per-vertex calculation across fragments. sqrt is one of those (the result of sqrt’ing a linear sequence of numbers is a curve), and your normalize is being done per-vertex and involves a sqrt, so the result of it will give artefacts when linearly interpolated. This is (one of the reasons) why for example per-vertex fog can appear banded compared to per-fragment fog: calculations that don’t linearly interpolate correctly are used. I reckon you’re in the same situation with your shaders.

So I guess you need to move some calculations to the fragment shader. vertexEye, lightPosEye and normalEye should become varyings and these lines should be moved to the fragment shader (with the appropriate changes to make them actually work in it, i.e. gl_FragColor instead of gl_FrontColor, etc):

	vec3 lightNormal = normalize(lightPosEye.xyz - vertexEye.xyz);
	gl_FrontColor.rgb = vec3(max(dot(lightNormal, normalEye), 0));
	gl_FrontColor.a = 1;