# Thread: Specular per-pixel lighting problem

1. ## Specular per-pixel lighting problem

I am using Blinn's formula to do specular lighting with ARB_VP and ARB_FP.
For every vector(in ARB_VP):
1)I compute the light vector and normalize it.
2)I compute the view vector and normalize it.
3)I compute H=L+V,normalize H and store it in texcoord[2]

For every fragment(in ARB_FP):
1)I get the interpolated texcoord[2],normalize it and store it in H.
2)I get the interpolated normal(N) from some other texcoord and proceed with the regular computations.

Now,for a reasonably large surface,the specular highlight is completely wrong.But,if i don't normalize the vectors in the vertex program and just keep the renormalization of H in the fragment program,the results look OK!

What do you think is happening?

2. ## Re: Specular per-pixel lighting problem

If one interpolates a normalized vector, opposed to a not normalized vector, those two results may be very different (that means, they show into different directions).

So don´t normalize your half-vector in the vp! Only normalize it in the fp.
A normalized vector usually behaves very different in most computations. Therefore one usually normalizes a vector just before the computation, which needs a normalized vector. The interpolation of the half-vector does not NEED normalized vectors, it can interpolate everything. However the results will be different (and incorrect with normalized vectors).

Hope that helps.
Jan.

3. ## Re: Specular per-pixel lighting problem

Surprise, surprise!

As long as you keep the output of the vertex shader linear (with respect to eye space), you will not witness any tesselation artifacts.

So move normalization from vertex shader into pixel shader, if you can afford it.

4. ## Re: Specular per-pixel lighting problem

Maybe I'm completly on the wrong track, but I think the opposite is true.
What you are basically saying is the following. If you interpolate between normalized vectors, you get wrong results, while when interpolating between the non-normalized ones, you get a correct result.

Take the following example. You have two vectors with directions perpendicular to each other. Now make one vector twice as long as the other. This result a very different vector compared to having it four times as long for example.
We all agree, that there can be only one right solution, so you have to use the normalized ones for interpolation.

Now on to the original question: If you have two normals that face in almost opposite directions, linearly interpolating between them results in a very short vector since the two normals' components almost cancel each other out.
If this vector gets small enough, the numerical errors present when doing the interpolation will probably result in a zero-component somewhere in your normal.
When renormizing, this component just stays zero and you get a wrong normal.
I don't know if it helps, but maybe you can scale all your normal in the vertex-program (as long as you scale them all with the same factor, you'll still get proper results).

Regards,

Jan

5. ## Re: Specular per-pixel lighting problem

L* = vertex position - light position, unnormalized
N* = vertex normal (carry though)

store these in texture coords
L* is linear in eye space, so will be without artifacts when interpolated

L = normalized( L* )
N = normalized( N* )
H = normalized( L + N )

This way you get 100% tesselation-agnostic per-pixel lighting. If you use H to calculate a reflection vector for env-mapping, you get 100% tesselation-agnostic reflection too.

The trick is to do the non-linear math in FP (expensive though).

6. ## Re: Specular per-pixel lighting problem

Originally posted by Jan2000:
If one interpolates a normalized vector, opposed to a not normalized vector, those two results may be very different (that means, they show into different directions).

So don´t normalize your half-vector in the vp! Only normalize it in the fp.
A normalized vector usually behaves very different in most computations. Therefore one usually normalizes a vector just before the computation, which needs a normalized vector. The interpolation of the half-vector does not NEED normalized vectors, it can interpolate everything. However the results will be different (and incorrect with normalized vectors).

Hope that helps.
Jan.
That's absolutely right. If you normalize H in your vertex program, the specular highlight will depend on the geometry (triangle shape). So never, ever do this. I think even Carmack has done this wrong, so he stated in a .plan some time ago:
"Per-pixel reflection vector calculations for specular, instead of an
interpolated half-angle. The only remaining effect that has any visual
dependency on the underlying geometry is the shape of the specular highlight.
Ideally, you want the same final image for a surface regardless of if it is
two giant triangles, or a mesh of 1024 triangles. This will not be true if
any calculation done at a vertex involves anything other than linear math
operations. The specular half-angle calculation involves normalizations, so
the interpolation across triangles on a surface will be dependent on exactly
where the vertexes are located. The most visible end result of this is that
on large, flat, shiny surfaces where you expect a clean highlight circle
moving across it, you wind up with a highlight that distorts into an L shape
around the triangulation line."

7. ## Re: Specular per-pixel lighting problem

Oh, and renormalizing N in the fragment program also gives slightly better bump mapping but results in very unpleasant aliasing. This could be resolved by building the mip maps of the bump map correctly yourself but i havn't tested this yet...

8. ## Re: Specular per-pixel lighting problem

Ok,I'll sum things up.
I want to use,if possible,an interpolated halfangle and not compute it for each fragment.

The problem is this:
If I normalize L and V,I get wrong results.
If L and V are unnormalized,I get correct results.
In both circumstaces,if I normalize H I get wrong results.
In fragment program,I normalize H with math.
I can understand why I shouldn't normalize H in vertex shaders(and instead do it in fp) but:

**Why L and V should be unnormalized when computing H for each vertex?**

Every document I've read says the opposite and even to me it doesn't sound right.
Can someone who has implemented per-pixel specular lighting and got things right describe what he has done?

9. ## Re: Specular per-pixel lighting problem

Well, i DID implement this, and i DID get it right.

jeickmann: What you describe is an artificial situation. The three normals which get calculated at the vertices and get interpolated get all computed with THE SAME FORMULA. Therefore they can be interpolated. What you describe would be completely different vectors, "picked at random". Of course that will make problems. Take a vector and its negative vector and try to interplate that. Normalized or not, it will fail. You have to play by the rules.

**Why L and V should be unnormalized when computing H for each vertex?**
They don´t. As i already said, you musn´t normalize the half-vector, but of course you have to normalize the view and the light-vector. If you don´t, your half-vector will point into unpredictable directions, resulting in wrong specular highlights.

If you do this, but get wrong results, then there is some other error in your code.

Maybe you have some normal in [0,1] range and forgot to put it into [-1,1] range? It´s easy to forget that. All normals in normalmaps are stored in [0,1] range.

Jan.

10. ## Re: Specular per-pixel lighting problem

Originally posted by Jan2000:
They don´t. As i already said, you musn´t normalize the half-vector, but of course you have to normalize the view and the light-vector. If you don´t, your half-vector will point into unpredictable directions, resulting in wrong specular highlights.
If you do this, but get wrong results, then there is some other error in your code.
Jan.[/QB]
I've thought of that,and checked my code for errors,but I can't find anything.The thing is,with higher tesselation,the results are correct.Are you sure the light and view vectors have to be normalized?As I read in Carmack's .plan posted,we must not use anything but linear calculations in vp:
"This will not be true if
any calculation done at a vertex involves anything other than linear math
operations."

And he states that calculating the half vector requires "normalizations"(plural),not normalization.The plural must imply the normalizations of light and view vectors.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•