Normal mapping, TBN matrix calculation

I just want to be sure that I understand the calculation of the TBN matrix correctly

In the vertex shader, we usually use:

vec3 n = normalize(gl_NormalMatrix * gl_Normal); vec3 t = normalize(gl_NormalMatrix * Tangent.xyz); vec3 b = normalize(gl_NormalMatrix * Bitangent.xyz); mat3 tbn = mat3(t, b, n); 

As I understand it, this tbn matrix converts a vector space from Tangent space to Eye . In fact, we want the opposite - to transform the vector from the space of the eyes into the space of touch. Thus, we need to invert the tbn matrix:

 tbn = transpose(tbn); // transpose should be OK here for doing matrix inversion 

note: tbn - should contain only rotations, for this case we can use transpose to invert the matrix.

And we can transform our vectors:

 vec3 lightT = tbn * light_vector; ... = tbn * ... 

In several source code tutorials, I found that the authors used something like this:

 light.x = dot(light, t); light.y = dot(light, b); light.z = dot(light, n); 

The above code does the same thing as transposed(tbn) matrix multiplication.

Question:

Should I use the transposed tbn matrix in the same way as I explained above? Or maybe I'm missing something?

Note In this solution, we have vectors (light_vector) converted to TBN in the vertex shader, then in the fragment shader we should get a normal normal map. Another option is to create a TBN matrix, which is transformed from the TBN space to the eye space, and then to transform the fragment shader, each of which reads the normal from a normal map.

+6
source share
1 answer

transposition is not an inverse of the matrix !!!

my TBN matrices in the vertex shader look like this:

 uniform mat4x4 tm_l2g_dir; layout(location=3) in vec3 tan; layout(location=4) in vec3 bin; layout(location=5) in vec3 nor; out smooth mat3 pixel_TBN; void main() { vec4 p; //... p.xyz=tan.xyz; pw=1.0; pixel_TBN[0]=normalize((tm_l2g_dir*p).xyz); p.xyz=bin.xyz; pw=1.0; pixel_TBN[1]=normalize((tm_l2g_dir*p).xyz); p.xyz=nor.xyz; pw=1.0; pixel_TBN[2]=normalize((tm_l2g_dir*p).xyz); //... } 

Where:

  • tm_l2g_dir is the transformation matrix from the local model space to the global scene space without any movement (only the direction changes) for your code - this is your normal matrix.
  • tan, bin, and are not vectors for the TBN matrix (as part of my models)

nor - normal vector to the surface from the actual position of the vertex (can be calculated as the vector multiplication of two vertices from this vertex)

tan, bin - perpendicular vectors, usually parallel to the axiomatic mappings of textures or testing of your model. If you select the wrong tan / bin vectors, some lighting artifacts can sometimes occur. for example, if you have a cylinder than the hopper, its rotation axis and tan are perpendicular to it in a circle (tangent)

tan, bin and should not be perpendicular to each other

you can calculate TBN also automatically, but it will cause some artifacts. for this, you simply chose as a tan vector one vertex used for normal calculations, and bin = or x bin

In the fragment shader, I use pixel_TBN with a normal map to calculate the real normal for the fragment

 //------------------------------------------------------------------ #version 420 core //------------------------------------------------------------------ in smooth vec2 pixel_txr; in smooth mat3 pixel_TBN; uniform sampler2D txr_normal; out layout(location=0) vec4 frag_col; const vec4 v05=vec4(0.5,0.5,0.5,0.5); //------------------------------------------------------------------ void main(void) { vec4 col; vec3 normal; col=(texture2D(txr_normal,pixel_txr.st)-v05)*2.0; // normal/bump maping normal=pixel_TBN*col.xyz; // col=... other stuff to compute col frag_col=col; } //------------------------------------------------------------------ 
0
source

All Articles