Precision of interpolated values

Hi, I’m doing eye-space phong shading/lighting.

I create my half angle vector like this:

vec4 eyePos = gl_ModelViewMatrix * gl_Vertex;
vec3 eyeVec = normalize(;

vec3 light = gl_LightSource[0].position - eyePos;

halfAngle = ( + eyeVec);

And then I normalize the halfAngle inside the pixel shader. I get very nice specular highlight.

Now. I think I should normalize the light vector and then multiply (light + eyeVec) by 0.5 to get the ‘correct’ halfAngle vector inside the vertex shader.
Unfortuantly, when I try this, the specular highlight doesn’t show up very well at all. If the angle between the halfangle and normal is very small it’ll show up, otherwise it disappears.
So the question is why is this happening. My first theory is that I’m losing precion if the length of these vectors is too small when outputed the from the vertex shader, but I’m not sure if that makes sense.
Anyone have any ideas. Do you normalize all your vectors before outputing them from the vertex shader?

Both, eyeVec qand light need to be normalized (or better to say: equal in length) in order to produce a correct halfvec. Muliplying with 0.5 gains nothing useful, you´d just make the vector shorter. Renormalizing it in the fragment shader will set its length back to 1 anyway.

Ya, the 0.5 is just a hack to get a ‘close to normalized’ vector since the two vectors I’m adding together are both normalized in this case. With or without the 0.5 though I still get bad results when this vector is normalized.

Judging your code above I don’t see either or eyeVec being normalized. You need to do:

halfAngle = normalize( + normalize(eyeVec);

Well I am normalizing the eye vector with the line:

vec3 eyeVec = normalize(;

But remember that my problem is that the lights look bad when things are normalized (just like the code you gave Hummus).
Here is my entire shader:

/**** VERTEX SHADER ****/
varying vec3 norm;
varying vec4 lightVec[1];
varying vec3 halfAngle[1];
void main()
vec4 eyePos = gl_ModelViewMatrix * gl_Vertex;
gl_FrontColor = gl_FrontMaterial.diffuse;
gl_BackColor = gl_BackMaterial.diffuse;
gl_FrontSecondaryColor = gl_FrontMaterial.specular;
gl_BackSecondaryColor = gl_BackMaterial.specular;
vec3 eyeVec = normalize(;
norm = normalize(gl_NormalMatrix * gl_Normal);
vec4 light;
light = gl_LightSource[0].position - eyePos;

This is the important line. If this line is commented out, things look nice, if it stays in, things look wierd
*******/ = normalize(;

lightVec[0].xyz =;
halfAngle[0] = ( + eyeVec) * 0.5;
gl_Position = ftransform();

varying vec3 norm;
varying vec4 lightVec[1];
varying vec3 halfAngle[1];
void main()
vec4 outcol = vec4(0.0, 0.0, 0.0, 0.0);
vec4 tempC;
vec3 lightV;
float lightDot;
vec3 normal = normalize(norm);
lightV = normalize(lightVec[0].xyz);
tempC = vec4(0.0,0.0,0.0,0.0);
lightDot = max(dot(lightV, normal), 0.0);
tempC += lightDot * gl_Color ;
tempC += pow(max(dot(normalize(halfAngle[0]), normal), 0.0), gl_FrontMaterial.shininess) * gl_SecondaryColor ;
tempC *= gl_LightSource[0].diffuse;
outcol += tempC; += vec3(gl_LightModel.ambient * gl_FrontMaterial.ambient); =;
gl_FragColor.a = gl_Color.a ;

Here are some videos of the results I get.
This is a single quad, 8x8 units wide centerd at (0,0,0). The camera is at (0,0,10). The light is at (x,0,1) and travels from about -5 to 5 in the x direction.

This video is when both light and eyeVec are normalized in the vertex shader. These are the bad results I’m getting when I’m doing the right thing. Notice how you can see the tesselated triagles as the light moves across. This is why the post is titled ‘interpation precision’

Now, here is a video where the line = normalize(;

is commented out.

And here are some extra examples, in this case
instead of a quad, the geoemtry is a 10x10 grid of quads, the geometry is still 8x8 units wide though and the light/camera are at the same position.


Is there anything obvious I’m doing wrong in the shader? I must be missing something here but I can’t figure out what. Thanks for all the help.

Malcolm Bechard

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