Regarding Tangent space

Hello Everyone,

I am reading about Normal mapping from OpenGL 4.0 Shading Language Cookbook. I could understand about the concept of tangent space. But I’m not able to understand how exactly the matrix is created for transforming vectors to the tangent space.

The matrix is generated like this:

Vertex Shader:


#version 400
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;

layout (location = 2) in vec2 VertexTexCoord;
layout (location = 3) in vec4 VertexTangent;

// .. Other uniforms

void main(void)
{
   // Transform normal and tangent to eye space
   vec3 norm = normalize(NormalMatrix * VertexNormal);
   vec3 tang = normalize(NormalMatrix * vec3(VertexTangent));

   // Compute the binormal
   vec3 binormal = normalize(cross( norm, tang ))
                           * VertexTangent.w;

   mat3 toObjectLocal = mat3(
                             tang.x, binormal.x, norm.x,
                             tang.y, binormal.y, norm.y,
                             tang.z, binormal.z, norm.z 
                            );

   // .. continues
}

Can anyone please explain this?
Thanks in advance!

Tangent, Bitangent (binormal is IMHO a terrible misnomer since this vector is tangential to the surface not orthogonal to it) and normal are the three basis vectors of tangent space. The matrix is simply a change of base from tangent space to object space (the space in which normal, tangent, bitangent are expressed).
Therefore its rows are the basis vectors of the source space (here: tangent space) expressed as vectors in the destination space (here: object space).

PS: I hope I didn’t mix up rows/columns in the above, but you get the idea :wink:

Bitangent (binormal is IMHO a terrible misnomer since this vector is tangential to the surface not orthogonal to it)

Not in this case.

The “Bi” in binormal refers to the tangent and normal vectors. It is “normal” to the “Bi”: tangent and normals.

The problem with the term “binormal” is that it assumes that the binormal is normal: orthogonal to the tangent and normals. It isn’t. In the above case it is, but that’s because the people who wrote the code were lazy and didn’t properly create a tangent space basis. A proper basis can have the tangent and bitangent not be orthogonal to one another.

“Bitangent” is a surface property, which may be orthogonal to the tangent and normal but does not have to be. “Binormal” is a geometric property which is, by definition, orthogonal to them.

So they refer to two different things. And since he’s constructing the binormal orthogonally, it is correct to call it “binormal”.

Thanks Alfonse Reinheart, Carsten Neumann.

@Carsten Neumann:

>> The matrix is simply a change of base from tangent space to object space

Well now i’m confused. Isn’t it from eye space to tangent space?

And since he’s constructing the binormal orthogonally, it is correct to call it “binormal”. [/QUOTE]
Another take on this:

Eric’s explanation makes more sense to me.

Well now i’m confused. Isn’t it from eye space to tangent space?

Ah, your code uses the vectors after applying the normal matrix, so yes it is between the eye and tangent spaces.