6
\$\begingroup\$

I'm learning environment mapping in OpenGL by following this page.

In his vertex shader, the author calculates the vertex normal in eye space with the following code:

nEye = vec3(viewMatrix * modelMatrix * vec4(vertexNormal, 0.0));

This works, but I've fooled around and made modifications to the shader code, so that it calculates the vertex normal with this code:

nEye = vec3(normalMatrix * vec4(vertexNormal, 0.0));

Where normalMatrix is a uniform 4x4 matrix I calculated outside the shader:

objectNormalMatrix = viewMatrix * modelMatrix;
objectNormalMatrix.invert();
objectNormalMatrix.transpose();

(I read from this question that the above is how you are supposed to calculate the normal matrix).

For either method of calculating the vertex normal I use, I get the same (working) graphical result, and this is what is confusing me.

My question is, why is(viewMatrix * modelMatrix) apparently equivalent normalMatrix? In calculating the normal matrix, I invert and transpose, but I do none of that when just multiplying by (viewMatrix * modelMatrix).

Here is some extra info that might be relevant:

  • The matrix library I use in my application is column major order (same as OpenGL).
  • When I pass my matrices to GLSL with glUniformMatrix, I have transpose as false.
  • The view matrix and model matrix in GLSL are uniforms from the application, and they are the exact same view matrix and model matrix matrices I use in my calculation of the normal matrix.
\$\endgroup\$
  • 5
    \$\begingroup\$ If viewMatrix * modelMatrix does not contain any shear or non-uniform scaling term, then the normal matrix is just the upper 3x3 of the modelview matrix, which has the same effect as multiplying the modelview by (x,y,z,0) instead of (x,y,z,1). Shear and nonuniform scale are fairly rare nowadays, which explicit meshes. \$\endgroup\$ – user41442 Mar 28 '15 at 22:40
  • 2
    \$\begingroup\$ @Jason Yup, when I apply a nonuniform scale to the model matrix, (viewMatrix * modelMatrix) doesn't work but normalMatrix does! Thanks for the help, I will accept if you post this as an answer. \$\endgroup\$ – Aaron Mar 28 '15 at 22:57
7
\$\begingroup\$

When a matrix is orthogonal, inverse and transpose are equivalent making an inverse transpose equal to the original matrix. So if your model view matrix is orthogonal, the normal matrix will be equal to it.

As user41442 pointed out, in most cases modelview matrices are actually orthogonal so this can be a bit of a short hand. There's still cases where it's not true so it's good to know when you can get away with it.

Rotation matrices are always orthogonal. Translations do not affect normals (assuming the w is zero on your normal). Uniform scales are not orthogonal, but they are direction preserving so re-normalizing after a uniform scale will give you the same normal. Therefore if you only use uniform scales, rotations and translations (and re-normalize your normals) you can treat the two as equivalent.

If you ever use non-uniform scales or shears on the other hand you need to calculate a proper normal matrix explicitly. This is also true if you don't have complete control over what transforms are used.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.