Problem on ATI with 5.6 drivers

Hi, I’ve written two shaders. One that does basic phong shading in eye space, and one that does bumpmapping in tangent space. Both of them work fine on nvidia hardware.

On ATI hardware the eye space one works fine but the bumpmapping one does not. In the bumpmapping on the light ends up being in the wrong spot. I’m pretty sure the problem is that gl_ModelViewMatrixInverse is incorrect. I use this to move the lights position to model space so I can move it into tangent space. I get the lights position with the line

vec4 lightPos = gl_ModelViewMatrixInverse * gl_LightSource[0].position

I have tried just using gl_LightSource[0].position on nvidia and I get a similar result as ATI, which leads me to believe the matrix I’m getting is the identity.

So the question is: is this a bug or am I missing something? The modelview matrix has the view matrix but not the model matrix in it when UseProgram is called.

Any thoughts are appreciated.

Thanks

If you’ve programmed things the usual way the Modelview matrix probably also contains your camera transform and your light position is in eye space. Multiplying by the inverse of the Modelview matrix will probably take you to world space, not model space.

By usual way I mean something like:

glLoadMatrixf( cameraMatrix );
glLightfv( GL_LIGHT0, GL_POSITION, lightVector ); // transforms by the ModelView matrix

{... push model transforms and draw here ...} 

If that’s the case you need to rotate your tangent and bitangent into eyespace the same way you would a normal.

vec3 n = gl_NormalMatrix * normal;
vec3 t = gl_NormalMatrix * tangent;
vec3 b = gl_NormalMatrix * bitangent;

vec3 lightdir; // calculate light direction in tangent space
lightdir.x = dot( gl_LightSource[0].position.xyz, t );
lightdir.y = dot( gl_LightSource[0].position.xyz, b );
lightdir.z = dot( gl_LightSource[0].position.xyz, n );

If that’s not the case then you’ll need to provide a little more info about how you’re setting up your light positions.

When UseProgram is called doesn’t affect the contents of gl_ModelViewMatrix and friends. It tracks whatever the current matrix is.

Hi, thanks for the reply.

Ya the light is specified basically as your said with a twist because its old code. Since we want the light at the same spot as the viewer the light position is specified more like

lightVector = cameraMatrix.inverse() * vector(0,0,0,1);
glLoadMatrixf( cameraMatrix );
glLightfv( GL_LIGHT0, GL_POSITION, lightVector );

(Ya I realize that we should just loadIdentity here instead, but bear with me, the code is old :slight_smile: )

So the light position should always just be at 0,0,0 in eye space.
Now I just did a test case where no transformation are applied to the model so model space = world space.
Since there are no model transforms when I render the modelview matrix still has just the camera matrix in it. So in this case the inverse should basically take me to model space. I then transform the light position to tangent space using tangent basis (composed of vectors in model space). This results in the same problem.

Your method does seem like it would work since it avoids having to use the Inverse modelview, but it doesn’t tell me why using the Inverse doesn’t work.

Remember that the code works perfectly on Nvidia hardware so its definetly a difference between the driver implementations. Has anyone experienced problems using this matrix?

Thanks again for the reply.

Oh sorry. The line “I have tried just using gl_LightSource[0].position on nvidia and I get a similar result as ATI” confused me and I thought you where getting the same results on both.

You might want to try the cheap debug trick out writing out the vectors of gl_ModelViewMatrixInverse into the fragment colour to check what exact matrix its giving you. Should be easy to tell if its always giving you an identity matrix and it is indeed an ATI driver bug.

If your matrix is orthonormal the inverse should be equal to the transpose so you could also just try replacing:

vec4 lightPos = gl_ModelViewMatrixInverse * gl_LightSource[0].position

with:

vec4 lightPos = gl_LightSource[0].position * gl_ModelViewMatrix;

I think what you’re seeing is a known bug where some Inverse matrixes actually contain InverseTranspose. Try transposing it and see if it turns out correct.

Yup that was it, using the transpose gave the desired results.

Thanks Hummus.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.