3

When we want to compute light in Vertex Shader we need normal vector in view space. In general it looks as below (from OpenGL Superbible 5th):

// normalMatrix is retrieved from GLMatrixStack modelViewMatrix
vec3 vEyeNormal = normalMatrix * vNormal

I want to write program without using GLT Library. In another source (http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Diffuse_Reflection) I found following formula:

vec3 normalDirection = normalize(m_3x3_inv_transp * v_normal);

Variable m_3x3_inv_transp is computed as follows:

glm::mat3 m_3x3_inv_transp = glm::transpose(glm::inverse(glm::mat3(mesh.object2world)));

I'm conscious that:

My question is why after inversing and transponsing matrix I get NormalMatrix and how to check it with reversing computations?

Community
  • 1
  • 1
CppMonster
  • 1,216
  • 4
  • 18
  • 35

2 Answers2

6

Your assumptions are not completely correct.

Order of OpenGL operations is Scalng, Translating, Rotating.

No, in general you can have an arbitrary world matrix. This can include any number of operations.

Inversing matrix is undo last transformation.

No. If you invert a matrix, its whole effect is reverted. E.g. if you have a matrix that rotates by 45° about the x-axis and translates by (1,2,3), its inverse would result in a translation by (-1,-2,-3) followed by a rotation by -45° about the x-axis.

Normal matrix is only rotation component of modelview matrix.

No. If this was the case, then you could just throw away the translation (and any perspective) part of the matrix. But it's not the case.

The normal matrix is used to transform normals so that they are still orthogonal to the according surface. For rigid body transformations (i.e. rotation and translation) you can directly use the world transform. One reason for that is that you can invert a rotation matrix by transposing it (because it's orthonormal). Then you have transpose(transpose(world)) which is the original matrix.

For general matrices you have to calculate the matrix as you stated. Imagine a scaling by (1, 2). If you transform a circle, it becomes an ellipse. Let's look at the normal at 45°. The circle's normal at this position is (1, 1) (unnormalized). If we transform this normal with the scaling matrix, we get (1, 2). If you imagine the transformed ellipse, the you'll see that the normal is not orthogonal to the surface anymore. So you have to use a different transform (in this case a scaling by (1, 0.5)) which preserves the orthogonality.

Nico Schertler
  • 32,049
  • 4
  • 39
  • 70
4

Answer based on p.66 of Mathematics for 3D Game Programming and Computer Graphics (by Eric Lengyel):

The tangent T and normal N at a particular point on a surface have to be perpendicular, so:

N . T = 0

Suppose we transform the surface using matrix M. The tangent at the point on the transformed surface is:

T' = MT

We want to find a matrix G such that N' = GN is the normal at the point on the transformed surface. Since the normal and tangent at the point on the transformed surface must still be perpendicular, we have:

0 = N' . T' = (GN) . (MT) = trans(GN) * MT = trans(N) * trans(G) * MT

Now:

trans(N) * T = N . T = 0

So the above would be satisfied if:

trans(G) * M = I

Whence:

G = trans(inv(M))

In other words, the matrix needed to transform the normal is the transpose of the inverse of the matrix used to transform the tangent.

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
  • If I good understand tangent vector (T) is always perpendicular to surface to generalize it for different-shaped surfaces and matrix M is for transforming vectors T, N and vertices of this surface? – CppMonster Jul 01 '13 at 13:48
  • @CppMonster: No, normal vectors are always perpendicular to the surface (by definition). Assuming the surface is a polygonal mesh, then M could be used to transform the vertices and the tangent vectors, but not the normal vectors. To transform the normal vectors, you need to use the transpose of the inverse of M, which is what the above is saying. – Stuart Golodetz Jul 01 '13 at 14:11
  • 1
    I've miswritten in haste (obviously N is perpendicular to surface, it's basis of this thread). I wanted to write that vector T is perpendicular to vector N to generalize different-shaped surfaces (if I have good understanding of tangents). Thanks for piece of information you gave me, because it was useful and valuable. – CppMonster Jul 01 '13 at 18:45