The daily lighting question ;-)

Hi! I’m calculating my specular like this:

DP3 temp, lightvec, normal;
MUL temp, temp, 2.0;
MAD temp, temp, normal, -lightvec;
DP3 LITin.y, temp, ViewVector;

The light and view vectors are normalized, so is the normal. It looks quite ok but not as the fixed function specular.

Do you know what’s wrong?
Thanks alot! / David
Btw I’m using LIT.

What is “normal”? Is it the face normal? If this is the case, it is wrong.
Instead of the face-normal you have to use the “half-angle” vector. You get it this way:

VECTOR a = Normalized (LightPos - VertexPos);
VECTOR b = Normalized (CameraPos - VertexPos);
VECTOR ha = Normalized (a + b);

If you wonder, why a and b have to be normalized, then there´s two of us. However if you don´t normalize them, you get a specular lighting, where the shape of the highlight is always a circle (and therefore very unnatural).

On the other hand, when you implement this stuff, you will get tesselation problems, cause then you will see, where two big polys share an edge. This can only be improved by tesselating the world, or by just using specular lighting only for small stuff.

But this is only the case for per-pixel lighting. I don´t really know how it looks if you do only vertex-lighting.
Are you implementing per-pixel or vertex-lighting?


If you wonder, why a and b have to be normalized, then there´s two of us. However if you don´t normalize them, you get a specular lighting, where the shape of the highlight is always a circle (and therefore very unnatural).

If you mean you wonder why you have to normalize the addition of a and b then it’s simple. Adding unit vectors never, at least I have never seen it happen, result in a unit vector. For instance, let a = [1,0,0] and b = [0,1,0]. Now c = a + b = [1,1,0]. Now the magnitude is sqrt( 1^2 + 1^2 + 0^2 ) = sqrt( 2 ). sqrt( 2 ) isn’t 1 so we don’t have a unit vector any more. Thus, we need to normalize the result of a + b.


No, i know why i have to normalize the result. But i didn´t know, why i have to normalize the other vectors. I implemented specular lighting just one week ago and got the tip to normalize the other vectors from this board.
I see a huge difference, but i didn´t really understand, why those other vectors have to be normalized, cause i always thought, that two vectors which point in the one direction, will always point in one direction when they get added, no matter how long they are.
However i just thought it through, and now it is quite clear to me. But i still think it´s not that intuitive at first, and you don´t learn that at school. But then there are a lot of important things, you don´t learn at school :wink:


It’s pretty simple why you have to normalize the light and view vector. It’s a question of balance.

But in reality, they need not be normalized. They just need to have the same magnitude.

OK, just ignore the first sentence and read the second one. It’s less confusing that way

Thanks for all replies! Yes I found out about the halfvector and used that instead, but it still didn’t look like the fixed function vertex lighting. The highlights “flickers” and shows up in wrong places, although it seems more accurate now than before. I can’t provide you with more details now, I have the code at work.
Thanks all again! I’ll investigate further on monday.

i think they have to be normalized becuase otherwise, the dot product does not represent cos(theta), but Length1Length2cos(theta).
when normalized, length is simply 1.

The final result (the half angle) has to be normalized in order be useful. The values a and b in the sum “a+b” do not have to be normalized. V-man is correct: a and b simply need their magnitudes to be the same in order to produce the half angle. Normalization is just one method to achieve that.


If a and b are not the same length, another method could be:
VECTOR ha = Normalize( a * Length(b) + b * Length(a) );

Heck, another way to calculate the half angle is by using the Cosine Law (a generalization of Pythagorean Theorem):
Symbol Notation: z^2 is zz
C^2 = A^2 + B^2 - 2
ABcos(a_b_angle); // where A,B,C are the scalar lengths of the vectors a,b,c
From a generalization of the Cosine Law we get an identity that states:
DotProduct(a+b,a+b) is identical to A^2 + B^2 + 2ABcos(a_b_angle) (Note there was only one sign change)
Which can be rewritten with vectors as: DotProduct(a,a)+DotProduct(b,b)+2

Thus, using the same variables in the previous posts we get:
VECTOR ha=(a+b)/sqrt( DotProduct(a,a)+DotProduct(b,b)+2*DotProduct(a,b) ); // a,b don’t have to be normalized

If a and b are both unity vectors (as mentioned by dbugger in his first post) then the calculation simplifies to:
VECTOR ha=(a+b)/sqrt(2+2*DotProduct(a,b))

Sorry. Couldn’t sleep last night. Nothing better to do.

David is using a correct Phong model. Is it defined that openGL fixed function uses the half vector variant or can it be driver dependant ? It should be more accurate to use the correct Phong model but if the OpenGL fixed function uses compensation for the specular exponent, then he might need to use the half vector varian instead…

Is there a “exact” definition of what openGL uses for the vertex light ?

Because of the flickering: Do you rotate that half-angle vector (or the light-vector, i´m not sure at the moment) into tangent-space?
If not, this could be the reason.