PDA

View Full Version : Circular specular highlight problem



inept
11-24-2002, 06:07 AM
Hello again,
Another separate problem, therefore another thread...

Could someone please give me some suggestions as to why my perpixel specular highlight is circular? It should become more eliptical the lower the viewpoint goes.

I'm using nv_vertex_program and nv_register_combiners (with light and halfangle lookups from a normalisation cubemap in 2 texture units).
Here's 3 screenshots showing the camera moving gradually up so you can see the shape and movement of the highlight... http://www.geocities.com/pixelshaderman/

Thanks for your patience.

inept
11-24-2002, 06:25 AM
Ah, no problem ... just found out that I needed to normalise the vertex-to-light and vertex-to-eye vectors....although I'm sure I tried this before and it didn't work (re-enforced by reading one of Nutty's demos which explicitly said not to normalise these vectors before interpolation http://www.opengl.org/discussion_boards/ubb/smile.gif ).
Sorry about that.

dorbie
11-24-2002, 07:36 AM
No, you need to use the famous half-vector for the specular dot product instead of the reflection vector. Your description of the circular reflection is exactly why the 'half way' vector is used. The half-vector is the vector half way between the light vector and the view vector.

[This message has been edited by dorbie (edited 11-24-2002).]

inept
11-24-2002, 07:49 AM
dorbie, I am using the half angle vector...it's calculated in my vertex program.
I still have the same problem, though. The reason I thought I'd fixed it was because I tesselated the plane to be 100x100, and the specular highlights started looking good (ie. eliptical at low camera elevation), but when I reduced the resolution of the plane mesh again, my highlight looked totally distorted (you could see it bending round the triangles).

Here's the latest nv_vertex_program:-




!!VP1.0

# c[0]-c[3] = modelview*projection matrix
# c[8] = light position in object coordinates
# c[9] = some useful constants:-
# .x = 0.5 used to compress signed vector into unsigned colour
# c[10] = view position in object coordinates

################################################## #####################
# Transform vertex position into clip space, using combined matrix (modelview and projection).
DP4 o[HPOS].x, c[0], v[OPOS];
DP4 o[HPOS].y, c[1], v[OPOS];
DP4 o[HPOS].z, c[2], v[OPOS];
DP4 o[HPOS].w, c[3], v[OPOS];
################################################## #####################


################################################## #####################
## DIFFUSE....... #
################################################## #####################

# Get vertex to light vector (L).
ADD R0, -v[OPOS], c[8];

# Transform L vector by Normal(NRML)/Tangent(TEX1)/Binormal(TEX2) orthagonal matrix to convert
# it into "tangent space" (aka "texture space" aka "triangle space")
DP3 R1.x, v[TEX1], R0;
DP3 R1.y, v[TEX2], R0;
DP3 R1.z, v[NRML], R0;

MOV o[TEX1], R1;

################################################## #####################
## SPECULAR....... #
################################################## #####################

# Get vertex to view vector (V).
ADD R2, -v[OPOS], c[10];

# create half angle vector (H) = (V+L)/2
ADD R2, R0, R2;
MUL R2, R2, c[9].xxxx; # divide by 2

# Transform H vector by Normal(NRML)/Tangent(TEX1)/Binormal(TEX2) orthagonal matrix to convert
# it into "tangent space" (aka "texture space" aka "triangle space")
DP3 R3.x, v[TEX1], R2;
DP3 R3.y, v[TEX2], R2;
DP3 R3.z, v[NRML], R2;

MOV o[TEX2], R3;

################################################## ######################
## Pass through other stuff... #
################################################## ######################

MOV o[TEX0], v[TEX0]; # move standard texture coordinates into normal map texture stage
MOV o[TEX3], v[TEX0]; # move standard texture coordinates into diffuse texture stage
MOV o[COL0], v[COL0];
MOV o[COL1], v[COL1];

END


Diffuse looks fine (ie. correct) but the specular is spherical (and when the light is very close to the triangle, the specular highlight is some distance away, when it should really be directly under the light).

inept
11-24-2002, 01:26 PM
Please help!
Just answer me this - it is possible to get an eliptical specular highlight over a single triangle, isn't it? There's no limitations of coord interpolation that I'm missing, is there?

dorbie
11-25-2002, 04:40 AM
Circular vs eliptical is definitely reflection vs half vector. As for distortion this can be caused by the linear interpolation of vectors. Local vectors like view and local light source need to be interpolated as positions not as vectors because the interpolation tracks off the correct vector direction and can show up as swimming that matches the geometry of your underlying triangle mesh.

The way to fix this is to renormalize after interpolation managing the per vertex direction using non unit vectors. It get's real tricky because you're trading precision in direction for interpolation accuracy. More subdivision of your geometry will help preserve vector direction and also mitigate any precision management issues if you decide to go that way.


[This message has been edited by dorbie (edited 11-25-2002).]

inept
11-25-2002, 05:22 AM
Thanks for your help dorbie, but you've seen the vertex program, and you can see how I'm calculating the half angle vector. What could be going wrong for me to end up with a reflection vector?
As for the col0/col1 interpolation problem, I just can't get enough accuracy with them, so I'll have to go for the normalisation cube maps - even the diffuse looks terrible on a large triangle.

davepermen
11-25-2002, 05:28 AM
well, you can't expect a correct result by doing perpixelcalculations per vertex. all you can calculate per vertex is actually the point to light and point to eye vector (both unnormalized. you need to normalize them per pixel, sum them up per pixel and renormalize per pixel to get the correct halfangle. that is technically more or less possible by using 2 normalizationcubemaps, and the approximated normalization function anrml(x) = (1+(1-dot(x,x))/2*x).

still thats not that precious.

you can get it with the reflection vector perfectly (except for precicion), as you _can_ reflect the normalized to eye vector perpixel and you still have a normalized vector to dot with the point_to_light. (except that your normal is in case of bumpmaps not normalized, again, the approx function is there way to go.. http://www.opengl.org/discussion_boards/ubb/biggrin.gif)..

i just start to _love_ my radeon9700, comparing your pic against my one.. http://www.itstudents.ch/users/dave/radeon9700.firstdemo.simpleperpixellighting.jpg
oh, and btw, my one is a circle as well. and i do.. hm.. where's my hd again, moment.. http://davepermen.homeip.net/projects/testgl/simple.fp.txt
i do it with reflection.. okay..