Just from model position, model normal and texture uv?

  • \$\begingroup\$ you need at least a right vector to ensure the TBN isn't rotated funny around the normal. upside is that you can calcuate that for each face from just the texture, pos and normal during the loading of the model \$\endgroup\$ Commented Oct 28, 2014 at 8:46

1 Answer 1


Yes. There an article about this by Chris­t­ian Schüler:
It's a followup to a book article (ShaderX 5) which did exactly what you need. I've used it myself.

Here is the part that you need: (p : world-space position, N : world-space normal)

mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv )
    // get edge vectors of the pixel triangle
    vec3 dp1 = dFdx( p );
    vec3 dp2 = dFdy( p );
    vec2 duv1 = dFdx( uv );
    vec2 duv2 = dFdy( uv );

    // solve the linear system
    vec3 dp2perp = cross( dp2, N );
    vec3 dp1perp = cross( N, dp1 );
    vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
    vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;

    // construct a scale-invariant frame 
    float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
    return mat3( T * invmax, B * invmax, N );

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .