Every vertex of a 3D mesh has position and some optional values like texture coordinates, vertex color, and normal, but also tangent and bitangent vectors.

While the purposes of texture coords, vertex color, and normal are pretty clear, I'm not understanding what tangent and bitangent vectors should be good for.

I am not asking about the mathematical definition, as I know that tangent and bitangent are vectors orthogonal to the normal and to each other.


1 Answer 1


Tangent and bitangent vectors are used for tangent space normal mapping / lighting and certain forms of displacement mapping.

In a tangent space normal map, we store the per-pixel normal in the colours of a texture pixel, expressed in the mesh's tangent space at that point. The usual convention is that the blue channel represents the mesh normal direction, pointing straight out from the surface, the red channel represents the tangent direction, pointing rightward along the texture map, and the green channel represents the bitangent direction, pointing upward along the texture map, according to the UV mapping used for that triangle.

That's why these normal maps usually look pale blue (most normals point out from the surface), with fringes of red and green where there are bumps, as though it were a relief lit from two sides with red and green lights.

Example Normal Map
Example tangent space normal map from the Knald Documentation

To do lighting with such a normal map, we need to transform the per-pixel normal and the light / eye vectors into the same coordinate space. Usually this is done by transforming the light and eye vectors into tangent space and doing our calculations there. In order to do that transformation, we need to know which way the tangent vector of the mesh points at the location we're shading, so we need the mesh's interpolated tangent vector so that we can construct the TBN matrix (tangent-bitangent-normal) to perform this transformation.

So if having our normals and lighting in tangent space requires this extra transformation step with a matrix we compute on the fly, you might understandably ask why we'd do it. Why not just store all our normals in object space and then transform with the uniform model matrix instead, and never need tangent vectors?

One reason is that tangent space normal maps are agnostic about the global orientation of the surface they're applied to. So we can re-use parts of a tangent space normal map on different parts of meshes, or even different meshes entirely - like a tiling brick pattern that might be re-used on walls in any orientation. Or with some tricks, we can mirror parts of the model that need the same surface colours/bumps, so we need half as much texture area to cover it (or can give it 2x the texture resolution within the same image size). Tangent space lighting also makes it easier to express the BRDF functions used in physically-based rendering to accurately model the reflective properties of different materials at different angles.

The other aspect I mentioned was displacement mapping - specifically forms that are called "relief mapping" or "parallax occlusion mapping", where instead of moving vertices around, we squish the texture samples/shading around in the fragment shader to get per-pixel displacement and occlusion of small surface bumps.

Here instead of a normal map, we have a height map expressing how high or recessed the surface should be at each point. When our view ray strikes a part of this height map that's over a valley, we need to extend that ray some distance until it hits the floor of the valley - which could be some distance away in UV space if the ray came in diagonally. So we need to do a form of raymarching to step our view ray along the texture to find the correct intersection point, and use those modified texture coordinates for the surface colour and shading. The TBN matrix again lets us transform the view vector into this space - since the mesh's tangent and bitangent directions point parallel to the texture axes (and, when prepared in a way that supports this use, also tell us the amount of texture stretching on each axis, so we can scale our steps accordingly).

More info about computing tangent space and its applications to displacement mapping in this answer.

  • \$\begingroup\$ This is a really good and detailed answer and I would upvote it if I could, but the reason I have not acepted it yet is there is something thet still not make much sence for mee. I mean having just the normal should be enough and do the job, replacing the normal by both tangent and bitangent could make sence, but having all 3 vectors at the same time seems redundant for me. \$\endgroup\$
    – convert
    Commented Feb 6, 2022 at 11:42
  • \$\begingroup\$ With just the normal, you know which way the blue direction of the texture should face, but you don't know how the texture plane is oriented at that vertex — you don't know where the green and red directions should point within the plane perpendicular to the normal. You're right that for normal mapping we can usually get away with just two vectors, so we store normal and tangent and then calculate the bitangent. However for displacement mapping we might need all three, because the texture map may be distorted and stretched, so the V direction is not exactly perpendicular or the same scale as U \$\endgroup\$
    – DMGregory
    Commented Feb 6, 2022 at 12:40
  • \$\begingroup\$ So do tangent and bitangent only make sence for textured meshes, or did I understand it wrong? \$\endgroup\$
    – convert
    Commented Feb 6, 2022 at 14:02
  • 1
    \$\begingroup\$ If you don't have a UV map, then you're definitely not using tangent space normal maps or displacement mapping, since both of those use UV maps. \$\endgroup\$
    – DMGregory
    Commented Feb 6, 2022 at 14:13
  • 1
    \$\begingroup\$ To find existing resources, the site to ask is a search engine. On StackExchange we'll write new content for you, rather than just link to stuff that exists. \$\endgroup\$
    – DMGregory
    Commented Feb 7, 2022 at 12:19

You must log in to answer this question.

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