Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 3 123 LastLast
Results 1 to 10 of 22

Thread: Specular per-pixel lighting problem

  1. #1
    Intern Contributor
    Join Date
    Jan 2004
    Posts
    78

    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. #2
    Senior Member OpenGL Guru
    Join Date
    Dec 2000
    Location
    Reutlingen, Germany
    Posts
    2,052

    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.
    GLIM - Immediate Mode Emulation for GL3

  3. #3
    Junior Member Regular Contributor
    Join Date
    Oct 2003
    Location
    Hamburg, Germany
    Posts
    118

    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. #4
    Junior Member Newbie
    Join Date
    Feb 2004
    Location
    Cologne, Germany
    Posts
    27

    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. #5
    Junior Member Regular Contributor
    Join Date
    Oct 2003
    Location
    Hamburg, Germany
    Posts
    118

    Re: Specular per-pixel lighting problem

    Calculate in Vertex shader:

    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

    Calculate in pixel shader:

    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. #6
    Junior Member Regular Contributor
    Join Date
    Mar 2002
    Location
    NI, Germany
    Posts
    114

    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. #7
    Junior Member Regular Contributor
    Join Date
    Mar 2002
    Location
    NI, Germany
    Posts
    114

    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. #8
    Intern Contributor
    Join Date
    Jan 2004
    Posts
    78

    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:
    In the vertex shaders,I compute:H=L+V
    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. #9
    Senior Member OpenGL Guru
    Join Date
    Dec 2000
    Location
    Reutlingen, Germany
    Posts
    2,052

    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.
    GLIM - Immediate Mode Emulation for GL3

  10. #10
    Intern Contributor
    Join Date
    Jan 2004
    Posts
    78

    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
  •