I'd like to understand how the process of building the "tangent space" matrix for normal mapping works. I'm following several tutorials, and other stackexchange questions, but I'm unfamiliar with the math involved, and a lot of resources seem to be telling me "just do this and it'll work".
According to the LearnOpenGL tutorial, you should build your tangent space matrix with the following code:
vec3 T = normalize(vec3(model * vec4(aTangent, 0.0)));
vec3 B = normalize(vec3(model * vec4(aBitangent, 0.0)));
vec3 N = normalize(vec3(model * vec4(aNormal, 0.0)));
mat3 TBN = mat3(T, B, N)
The first three lines are variations of:
vec3 worldSpaceVec = normalize(vec3(modelMatrix * vec4(modelSpaceVec, 0)));
Other implementations I've seen do:
vec3 worldSpaceVec = normalize(mat3(modelMatrix) * modelSpaceVec);
(by the way, I'm not sure I visualize why the LearnOpenGL tutorial doesn't use vec4(modelSpaceVec, 1)
; I'm not sure what either value would represent or how it would change the results. I assume this just a property of normals that we always represent them with a w
of 0, but I don't get why it applies to the tangent and bitangent)
But more importantly, I don't understand the modelMatrix * ...
part of the equation. According to this answer, normals are bivectors, a different type of data which is represented by a row matrix instead of a column matrix (that is, bivectors are $\begin{bmatrix} x & y & z \end{bmatrix}$ where vectors are$\begin{bmatrix} x \\ y \\ z \end{bmatrix}$).
If my understanding is correct, then normals are of a different type than regular vectors, just like kilograms and liters are similar but different types; and they need to be treated differently in regard to transformations. So why does the tutorial use:
vec3 worldSpaceVec = normalize(vec3(modelMatrix * vec4(modelSpaceVec, 0)));
and not
vec3 worldSpaceVec = inverse(transpose(modelMatrix)) * modelSpaceVec;
or even
vec3 worldSpaceVec = inverse(transpose(mvpMatrix)) * modelSpaceVec;
?
In other words, should the tangent and bitangent vectors of a vertex be converted from one space to another using the same transformation matrix as the vertex's normal vector, and if so, why?