GLSL and TBN matrix - Is my understanding correct?


I just compared these two articles:
Article 1
Article 2

In Article 1 a TBN matrix is calculated which
transforms a point from tangent to object space:
(Tx, Bx, Nx)
(Ty, By, Ny)
(Tz, Bz, Nz)

Then they calculate the inverse of this matrix which
can transform a point from object to tangent space
and use this matrix in the shader here.

In Article 2 the TBN matrix (or the TBN vectors)
is calculated like this:

generateNormalAndTangent(float3 v1, float3 v2, text2 st1, text2 st2)
  float3 normal = v1.crossProduct(v2);
  float coef = 1/ (st1.u * st2.v - st2.u * st1.v);
  float3 tangent;
  tangent.x = coef * ((v1.x * st2.v)  + (v2.x * -st1.v));
  tangent.y = coef * ((v1.y * st2.v)  + (v2.y * -st1.v));
  tangent.z = coef * ((v1.z * st2.v)  + (v2.z * -st1.v));
  float3 binormal = normal.crossProduct(tangent);

The code is nearly the same except that the input parameters
are already direction vectors. But the main difference is
that no inverse matrix is calculated.

Now my question:
Since there is no inverse calculated in Article 2
I would say this function calculates a TBN matrix which
transforms from tangent to object space. So first I was
wondering if the plan is really to transform all normal
map texture values from tangent to object space.

But I think the solving is in the shader because there
I found the following code:

v.x = dot (vertexPosition, t);
v.y = dot (vertexPosition, b);
v.z = dot (vertexPosition, n);
eyeVec = normalize (v);

The way the dot products are applied I would say
vertexPosition is multiplied with a TBN matrix
that looks like this:
(Tx, Ty, Tz)
(Bx, By, Bz)
(Nx, Ny, Nz)

This is the transpose (and thus the inverse, since
the matrices are orthogonal) of the matrix that
transforms a point from tangent to object space
as mentioned at the beginning of my post, right?

So to sum up. Is my understanding correct that the
approach in Article 2 calculates a TBN matrix
that transforms from tangent to object space and
then later in the shader the transpose of this
matrix is used as inverse matrix to transform
from object to tangent space (actually from
eye to tangent space because of the multiplication
with the normal matrix)?

If yes then I would prefer the second approach
since it requires less calculations and code.

Please let me know if I am wrong? Thanks!!

Best regards!

It doesn’t matter where (in what coordinate space) you are performing lighting calculations. You are just given light & camera vectors in (to say) world space and a normal (from the bump texture) in the tangential space. You can either transform first two vectors into the tangential space (in vertex shader -> cheaper) or convert the extracted normal back to the world/camera space (in fragment shader).

Knowing that TBN matrix is ortho-normal, so you can inverse it by transposition (or just multiply it by a vector in a special way), it makes no difference how you construct it from your 3 vectors.

The conclusion:
-construct TBN in any way you like
-choose the coordinate space to perform lighting calculation in
-transform either camera&light vectors or a normal vector into your calculation space
-see the beauty of the result!

Hi Dmitry,

yeah that’s clear that one can choose the space.
My question was more if my understanding of Article 2
is correct. In the meantime I got an email from the
author of this article and he confirmed that the way
he applies the dot product results in some kind of
“multiply with inverse TBN matrix” :slight_smile: