Specular lighting shader vs. fixed functionality

So, I’ve been playing around with trying to get a lighting shader to work. I basically just want it to do the exact same thing as the fixed functionality OpenGL lighting, except per fragment instead of per vertex.

I’ve tried several of the ones I’ve found on online, but none of them seem to match the fixed functionality of OpenGL. I am working under the assumption that the OpenGL lighting is “correct” and it’s just the per-vertex approximation that makes it look less than optimal. If this is not the case, please let me know. Stemming from this assumption, I assumed that when the camera is stationary, but rotating back and forth, that the specular patches should move around. This happens in the fixed functionality version, but in half of the Phong lighting model shaders I find online, the specular patches are strictly stationary. These are based off the modelview matrix, so maybe I am segregating the modelview and projection matrix operations incorrectly; I will specify how I do that later.

There are shaders I have found online that move, but they are seem to move more drastically than the fixed functionality, and the patches are in a different spot on the object (just using a sphere for now). I even tried generating a shader using 3D Labs ShaderGen to mimic fixed functionality, but it does the same thing (moves more dramatically, and is in the wrong spot).

As mentioned above, I figure this could stem from my segregating my modelview and projection matrix operations in some non-standard way, but even if I do, I would have thought this would have broken fixed functionality in the same way as the shaders (hence they would both be wrong, but wrong in the same way).

My projection matrix is Identity * my gluPerspective() call, and my modelview matrix is then Identity * my gluLookAt() call * whatever the objects own display matrix is. If this is non-standard, and you think it could be what is breaking the shaders, please let me know how they would anticipate them being.

I wouldn’t have thought it would be that hard to make a shader that matched the fixed functionality of OpenGL (assuming that is a desirable lighting model), hence I assume I’m just doing something else wrong.

Any ideas?

I was mistaken previously about ShaderGen’s fixed functionality shader not being correct. It was my first time using it, and apparently it was generating a shader for a directional light, not a point light.

Perhaps, the other one that was moving, but too quickly and in the wrong place was designed the same way.

This reduces my question to a slightly simpler one. Is the OpenGL fixed functionality accurate in that the specular patches shift when the eye is stationary, but rotating? If so, why do most of the shaders I find online generate specular patch that is stationary? Something like:


varying vec3 normal, lightDir, eyeVec;

void main()
normal = gl_NormalMatrix * gl_Normal;

vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);

lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);
eyeVec = -vVertex;

gl_Position = ftransform();		



varying vec3 normal, lightDir, eyeVec;

void main (void)
vec4 final_color =
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
(gl_LightSource[0].ambient * gl_FrontMaterial.ambient);

vec3 N = normalize(normal);
vec3 L = normalize(lightDir);

float lambertTerm = dot(N,L);

if(lambertTerm > 0.0)
	final_color += gl_LightSource[0].diffuse * 
	               gl_FrontMaterial.diffuse * 
	vec3 E = normalize(eyeVec);
	vec3 R = reflect(-L, N);
	float specular = pow( max(dot(R, E), 0.0), 
	                 gl_FrontMaterial.shininess );
	final_color += gl_LightSource[0].specular * 
	               gl_FrontMaterial.specular * 

gl_FragColor = final_color;			


Any ideas?

i cant really understand the posts, but the shader above is using per-pixel lighting whereas FFP can only use it per-vertex and then interpolating per-pixel.

“If so, why do most of the shaders I find online generate specular patch that is stationary?”
to keep it simple?

So am I correct in inferring from your statement that the stationary specular patches are indeed less correct, and just a less computational expensive approximation, in comparison with the shaders that generate the specular patches that move a little?

If you choose to implement specular mapping, the specular spot must move since it depends on light and eye positions. The OpenGL fixed pipeline computes gouraud shading which is per-vertex lighting but it does not prevent to implement correct specular mapping (on the movement side) as you said. So, there is only a coding issue in your shader.

Your code is far from being optimal and a bit complicated for phong shading. I did not read it deeply enough to find a bug, I suggest you instead to compare with another one here:

By the way, why do you revert the ‘L’ vector when calling the reflect function? I am not used to use it, I may miss something, but I would not do that. I know this is not the problem here, it does not event the specular spot to move.

First of all, that isn’t my code, it is one I found online that happens to behave like several others I found.

The lighthouse3d shader you linked was actually the first one I started with. However, as mentioned above, while doing something that appears close to right, it didn’t match the behavior of the OpenGL fixed functionality, as far as position of patch goes.

If I recall correctly, that shader’s patch did move, but it seemed to move faster than the OpenGL fixed functionality’s patch, and it seemed to not be in the same place. That’s why I wondered which was correct.

Here’s an example of one I found that generated a smooth patch, but didn’t move at all:

Vertex Shader:

varying vec3 N;
varying vec3 v;

void main(void)
v = vec3(gl_ModelViewMatrix * gl_Vertex);
N = normalize(gl_NormalMatrix * gl_Normal);

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

Fragment Shader:

varying vec3 N;
varying vec3 v;

void main (void)
vec3 L = normalize(gl_LightSource[0].position.xyz - v);
vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)
vec3 R = normalize(-reflect(L,N));

//calculate Ambient Term:
vec4 Iamb = gl_FrontLightProduct[0].ambient;

//calculate Diffuse Term:
vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);
Idiff = clamp(Idiff, 0.0, 1.0);

// calculate Specular Term:
vec4 Ispec = gl_FrontLightProduct[0].specular
* pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
Ispec = clamp(Ispec, 0.0, 1.0);

// write Total Color:
gl_FragColor = (gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec);

If I recall correctly, that shader’s patch did move, but it seemed to move faster than the OpenGL fixed functionality’s patch, and it seemed to not be in the same place. That’s why I wondered which was correct.

I can not assure that, but IMO, the fact that it is not moving the same way is because, unlike the fixed pipeline the lighthouse3D shader implements Blinn-Phong shading which rely on the half vector between the view and the light one. This lighting model is faster but is an approximation of the Phong model (the one you have implemented) thus does not give exactly the same result.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.