2

Let's say you have a 3D mesh with normal map provided with. The mesh owns as well tangents, bitangents and normals.

From the tangents, bitangents and normals, you could build the TBN matrix that is a matrix that transform tangent space to world space. That way, to get the real normal you just have to do something like that :

mat3 TBN = mat3(tangent, bitangent, normal);
vec3 realNormal = TBN * normalFromTheNormalMap;

However, how to get the real tangent and bitangent from this system?

Antoine Morrier
  • 3,930
  • 16
  • 37

1 Answers1

3

You have to Orthogonalize the vectors. A common way for the Orthogonalization is the Gram–Schmidt Orthonormalization.

This algorithm uses the circumstance that, the dot product of 2 vectors is equal the cosine of the angle between the 2 vectors multiplied by the magnitude (length) of both vectors.

dot( N, T ) == length( N ) * length( T ) * cos( angle_N_T ) 

This follows, that the dot product of 2 unit vectors (normalized vectors) is equal the cosine of the angle between the 2 vectors, because the length of a unit vector is 1.

uN = normalize( A )
uT = normalize( B )
cos( angle_T_N ) == dot( uT, uN )

enter image description here

If realNormal is a normalized vector (its length is 1) and tangent and binormal are orthogonal, then the realTangent and the the realBinormal can be calculated like this:

realTangent  = normalize( tangent - realNormal * dot(tangent,  realNormal) );
realBinormal = binormal - realNormal * dot(binormal, realNormal);
realBinormal = normalize( realBinormal - realTangent * dot(realBinormal, realTangent) );

If tangent and binormal are normalized vectors too, then the normalize function can be substituted by dividing with the dot product of the source vector and the real vector:

realTangent   = tangent - realNormal * dot(tangent,  realNormal);
realTangent  /= dot(tangent, realTangent);
realBinormal  = binormal - realNormal * dot(binormal, realNormal);
realBinormal  = realBinormal - realTangent * dot(realBinormal, realTangent);
realBinormal /= dot(binormal, realBinormal);

See further How to calculate Tangent and Binormal?.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • You do not need to project the binormal on the realTangent also? Because in the graham schmidt process, you need to project (n - 1) times for the nth vector – Antoine Morrier Sep 19 '17 at 20:12
  • A last question, is it the same if I compute the bi normal BEFORE the tangent, or is it not the same? – Antoine Morrier Sep 19 '17 at 20:36
  • @AntoineMorrier You can change the order, but it is not exactly the same if you do `realBinormal = realBinormal - realTangent * dot(realBinormal, realTangent);` in compare to `realTangent = realTangent - realBinormal * dot(realBinormal, realTangent);`. Both will give orthogonal vectors, but slightly different. – Rabbid76 Sep 19 '17 at 20:39