Archived

This topic is now archived and is closed to further replies.

Poya

Per Pixel Specular Problem

Recommended Posts

Hello I have seccessfully been able to aply per-pixel diffuse and specular lighting in 2 passes. Both passes use the normalization cubemap to fetch normalized light, and half-angle vectors respectively. At the moment for specular lighting I raise the result of the dotproduct to 16th power, in the pixel shader which although looks pretty good causes some banding. These are my questions: 1) Now I have read here and there that when using a normalization cube map you shouldn''t normalize the vectors at each vertex (which you pass to the cube map) because interpolations won''t be correct. This is fine with diffuse lighting: you just pass the unnormalized light vector. In the case of specular however, don''t you need to normalize the light and view vectors before adding them to get the half-vector? At the moment I add them without normalizing (or equating their lengths) and although the result looks correct I''m not sure if the half angle I''m getting is what it should be. 2) I''ve been trying to implement a specular map lookup table so I can get rid of the banding. But I simply cannot find a way of doing this. All the examples I''ve found (including nVidia, MSDN and gamedev articles) use: texm3x2pad texm3x2tex but I cannot see how I can use the normalization cube map to get normalized half angle vectors. In the examples I spoke of they normalize the half angle vector on a per-vertex basis which means the commands above would work. Not really useful for a point-light and a large poly. I tried doing the dot3 of half vector and surface normal, like I do now, then use the result to access the specular lookup texture using the texreg2gb command. But this doesn''t work. If I understand correctly I cannot use texture access commands after arithmetic ones. Can anyone help me with this, or point me in the right direction? Thanks in advance, Poya

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Poya
Hello

1) In the case of specular however, don''t you need to normalize the light and view vectors before adding them to get the half-vector? At the moment I add them without normalizing (or equating their lengths) and although the result looks correct I''m not sure if the half angle I''m getting is what it should be.
When you add two vectors of different lengths, the vector with the larger magnitude is going to weigh more in the result that the shorter vector, skewing it. Normalizing both vectors makes sure they are weighted evenly.
quote:
Original post by Poya
I cannot see how I can use the normalization cube map to get normalized half angle vectors. In the examples I spoke of they normalize the half angle vector on a per-vertex basis which means the commands above would work. Not really useful for a point-light and a large poly.

Thanks in advance,
Poya
When you add the normalized vectors together, your half angle magnatude will be greater than length one. The cube map look up uses the greatest valued component of the vector to select the correct face. (I''m sure you already know that).

As for your second question, I regret I''m unable to answer it as of yet. However, I do know that the Pixel Shader Tutorial (linked on main page of gamedev.net) has a solution for banding in the roxor 8 sample. I''m sure that it uses ps1.4, but it might be something you could work to in a lower ps version if need be.

-James

Share this post


Link to post
Share on other sites
I tried normalizing the light and view vectors before adding to get the half angle. Unfortunately it gives very incorrect results once normalized with the cubemap. As I mentioned before (and I also found other people saying the same thing) is that while two different length vectors (pointing in the same dirrection) choose the same face in a cube map, the would interpolate differently accross the edges of the poly and would therefore give different results. The only solution I could get my hands on is to pass BOTH UN-normalized view vector and light vector to the pixel shader and normalize both with normalization cube maps, then find the half-angle in the pixel shader rather than the vertex shader. Mind you, at the moment I''m adding light and view vectors in the vertex shader to get the half angle, without normalizing or scaling in anyway. I understand that this is mathematically incorrect but it seems to give very good results (no skewing as the last poster suggested)

My main problem, however, is the banding caused by high powers of specular (16 in my case.) The only solution which I have been able to gather around from different sources, is to add some random noise. Any other suggestion? Any ideas how i could add random noise in a pixel shader? Again any ideas or help would be appreciated.

Thanks

Share this post


Link to post
Share on other sites
No help, I just wondered how you access a lookup table from the shader - where do you store it?

One thought - how does the fixed-function option do non-banded specular lighting? Maybe you could just copy that in shaders?



Read about my game, project #1
NEW (13th August): A new screenshot is up, plus diaries for week #3


John 3:16

Share this post


Link to post
Share on other sites
The fixed function pipeline does the specular per-vertex and not per-fragment, and therefore looks nowhere near as nice (It doesn''t take into acount the bumpiness of the surface, ie the normal map)

The way I tried to use the specular lookup was to store the powers in a texture. At each pixel the color is Y^16, where Y is the vertical component in the texture. So as you move down the texture the color is exponentially brighter (white)

Then you use the following in the pixel shader

texm3x2pad t2, t1_bx2 ; u = t1 dot (t2) half vector
texm3x2tex t3, t1_bx2 ; v = t1 dot (t3) half vector

t1 is the normal map
t2 is any texture
t3 is the specular lookup

coordinates stored in t2 and t3 are the half vector

This performs a dot3 between the half-vector and surface normal at that fragment and samples t3 (our lookup table) using the results of the two dot3s (ie U and V), therefore t3 should have the correct specular brightness now.

The main problem with this method is that you cannot at any stage include a cubemap normalization for you half angle vector (ie you have to normalize it in the vertex shader and hope the poly is small enough) This looks very incorrect with large polygons.

Share this post


Link to post
Share on other sites