Contents

1. Preface
2. Disclaimer
3. What you need to know on beforehand
4. Introduction
5. Theory
5.1. A Practical Example
5.2. The difference between texture space and tangent space
5.3. Choosing the right type of geometry
6. Derivation
6.1.a Exploiting the Properties of a Orthonormal Matrix
6.1.b The inverted tangent space matrix
7. Analysis of the derived matrix
8. Conclusion
9. References

1. Preface

Have you ever wondered what this tangent space everybody's talking about is? Or perhaps you've grown tired of everybody making use of a matrix you don't even know where comes from in the first place!
Look no further! It's time for you to dig down in those nittygritty's and find out where it all comes from.
Put on your helmet and get ready for a wild ride while we derive the tangent space matrix.

2. Disclaimer

Don't take everything for granted. Don't just blindly believe in everything that's said. If you think something looks weird in the article don't just skip it but instead question it and confront the authors!

3. What you need to know on beforehand

Basic knowledge about vectors and their operations
What matrices are and a basic understanding of the operations performed on them
Basic OpenGL knowledge

4. Introduction

As most graphics programmers probably know diffuse lighting is calculated by performing a dot product between a surface normal and a light vector (if you don't know what we're talking about have a look at [1]. For this dot product to make sense it's required that these two vectors exist in the same space (coordinate system). Usually we choose the surface's coordinate system (in which the surface normals exist) since this means we only have to convert the light vector for each vertex on the surface into this space which means the light vector can be linearly interpolated across the surface. Another option would have been to convert all the surface normals (and there could be a lot) to the light vector's coordinate system. You probably see which method is preferable!
The purpose of this article is to find the matrix that enables us to convert a set of coordinates (e.g. the light vector's coordinates) from world space (in OpenGL, the modelview matrix) to tangent space. We'll refer to this matrix as the Tangent Space Matrix (TSM).

5. Theory

For most graphics APIs world space is defined by the three basis vectors,
These are also known as the columns of the identity matrix. If we multiply a vector by the identity matrix it will be converted to the same coordinate system.

5.1. A Practical Example

Let's compare the previous section with something that most OpenGL users should be familiar with: the modelview.

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(...);
glVertex*(...);
...
glEnd();

In the example code above the modelview matrix is set to the identity matrix. When rendering the vertices following the glBegin() call, their position won't be changed (no translation or rotation is performed) since they're multiplied by the identity matrix. This should be common knowledge to all OpenGL users.

5.2. The difference between texture space and tangent space
Texture space:

The dimension of texture space is given by the following OpenGL constants

GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D

The texture coordinates are referred to as (S, T, R).
These coordinates are manipulated by a texture matrix.

glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glBegin(...);
glTexCoord*(...);
...
glEnd();

In the example code above the texture matrix is set to the identity matrix (which it is by default). This will in turn mean that the specified texture coordinates (when rendering) won't be changed (translated or rotated).

Tangent space:

Since our use of the tangent space concerns a limited plane (in the shape of a polygon) the corresponding normal map will be of the dimension 2 (in other words, a 2D map). Essentially, this means that each vertex will have two texture coordinates specified  an S and a T component.
A normal map is made up so that there for each texel is specified a normal to that texel's surface. Those normals are said to exist in tangent space for which the dimension is 3.
The axes for the tangent space directly depend on the geometry of the polygon and the corresponding texture coordinates, which are described in the following.


The red, green and blue arrows on the left of figure 1 constitute world space (the axes aren't named since their names don't matter in this discussion, nor do their directions). The three other axes to the right in figure 1 constitute the basis vectors for the triangle's tangent space. v and c denote the vertex and texture coordinates for a given geometric point, respectively.
As mentioned previously, we want to determine the matrix that transforms a vector in world space (the three colored axes) to tangent space (the three black axes).

5.3. Choosing the right type of geometry

In figure 1 we've drawn a polygon in the shape of a triangle. By choosing this exact type of geometry the matrix we're seeking will be identical for all three vertices since they will be in the same plane.
"three points in 3D space is the minimum number necessary to create a plane"
This means that if we're using a type of geometry which contains arbitrary polygons or even quads one would have to calculate a tangent space matrix for every single vertex since we don't know if those vertices lie on the same plane (which they in most cases won't).
"if the amount of vertices that define a geometric surface don't exist in the same plane,
one has to calculate a tangent space matrix for every single vertex"
The calculated matrices will then be linearly interpolated across the rendered surface.
By now it should be quite clear that utilizing triangles when dealing with the tangent space matrix is quite an optimization!

6. Derivation
Goal: The basis vectors of the tangent space matrix are to be found


Let's write out what we know by now:
 vertex coordinates: v1, v2 and v3 exist in world space
 texture coordinates: c1, c2, c3 exist in texture space
We further note that,
 The vector from v1 to v2 has the same direction in world space as the vector from c1 to c2 in texture space.
 The vector from v1 to v3 has the same direction in world space as the vector from c1 to c3 in texture space.
Some notations:
 We denote the vector from v1 to v2:
 We denote the vector from c1 to c2:
 We denote the vector from v1 to v3:
 We denote the vector from c1 to c3:
The vectors are denoted by the (delta) sign since the vector is, essentially, the difference between two sets of numbers.
The components of a vector are referred to as:
The unknown basis vectors for the tangent space matrix will be referred to as T (tangent), B (binormal) and N(normal).
In figure 3 below the connection between a vector in world space and two arbitrary unknown basis vectors (T and B) is shown.


From the figure it's easy to see that is formed as a combination of the two unknown basis vectors.
If we look at the connection between the vectors and , the texture vector's 1. coordinate, , will be the scalar of the basis vector T and the texture vector's 2. coordinate, , will be the scalar of the basis vector B, which determine the influence T and B, respectively, have on the final vector .
Like this we can set up an equation which reflects exactly this property.
Furthermore, there is a known connection between and as well
Hence, we have two equations with two unknowns. These can be set up in a system of two equations, as shown to the right in the following:
The solution to this system is
Notice that the denominator is the determinant of the coefficient matrix
If we take this a step further the solution will end up on the following form
This results in two linearly independent basis vectors for the tangent space
Now, all we need is a third vector which too is required to be linearly independent from the two others. A cross product will do this for us
The three basis vectors can then be set up in a matrix
This matrix will take any vector in tangent space and transform it into world space.
, which is, in fact, the direct opposite of what we want.
The matrix that will do the opposite job would be the inverted matrix .
You might have noticed that the new matrix is a 3x3 matrix, which will greatly ease the calculation required to find the inverted matrix (which is probably known to skilled mathematicians).

6.1.a Exploiting the Properties of a Orthonormal Matrix

(Section included the 15 dec. 2007)
In most applications of the TBN matrix a certain special case is far the most present. It is therefore worthwhile to consider some important properties of this case. We are considering the case where the tangent and bitangent vectors are orthogonal, which simply means that the TBN matrix is preserving the angles between two vectors when rotating them from one space into another. It is often the case in computer graphics that the texture space is not squeezed relatively to the surface it is presented on, because this would reduce the samples and result in a decreased quality of the shading.
When the two tangent vectors are ensured to be orthogonal the TBN matrix is guaranteed to be orthonormal. An orthonormal matrix has the property that its inverse is equal to its transpose. If this is exploited the inverse tangent space matrix is already obtained and we are done. Note that the TBN matrix can be passed in its transpose form directly to the vertex shader.
In the next section, it is shown how to compute the the inverse matrix in a more general way, but remember that the TBN matrix is very often orthonormal and that in this case one should exploit that the transpose equals the inverse.

6.1.b The inverted tangent space matrix

When the inverted matrix has to be calculated we make use of the matrix's determinant
The inverted matrix is given by
Notice that the positions of the negative signs are organized in a system.
If we ignore the negative signs for a second, the following hold true:
 1st row is the cross product between B and N
 2nd row is the cross product between N and T
 3rd row is the cross product between T and B
We can then set all this up in a generalized expression for an inverted 3x3 matrix
q.e.d.

Small Note

Remember that only needs to be calculated once!

7. Analysis of the derived matrix

The tangent space matrix only needs to be recalculated if the polygon has been rotated. It should not be recalculated after a translation since the axes of the tangent space coordinate system will still have the same direction after such a transformation.
Let's imagine that a given surface is rotated during runtime such that the precalculated matrix no longer is valid.
Let's write out what we know to begin with:
 The distance between v1, v2 and v3 as well as c1, c2 and c3 is unchanged during the rotation.
 The vectors and have to be updated. However, and are left unchanged (6 subtractions).
 The determinant is unchanged since it depends on and .
Calculation of T and B is given by a multiplication of two matrices and a constant and requires 8 operations (6 multiplications and 2 subtractions).
The vector N is found by doing a cross product between T and B and required 9 operations (6 multiplications and 3 subtractions).
Calculation of the determinant requires 17 unavoidable operations (12 multiplications, 3 subtractions and 2 additions).
The three cross products BxN, NxT and TxB require 27 operations (18 multiplications and 9 subtractions).
Setting up the cross products in a matrix requires 4 operations (4 subtractions).
Calculation of the inverted tangent space matrix requires 10 operations (9 multiplications and 1 division).
An overview of the process is outlined in the following table.


Addition

Subtraction

Multiplication

Division

Sum




6





6

T and B



2

6



8

N



3

6



9


2

3

12



17

BxN, NxT and TxB



9

18



27

Setting up of



4





4

Calculation of the inverted TBN matrix





9

1

10

Sum

2

27

51

1

81


This is the minimum number of operations required to create a TBN matrix at runtime for the given example.

8. Conclusion

In this article we've discussed a robust approach to calculating the tangent space matrix for an arbitrary surface at runtime. We've tried to shed light on where this mysterious matrix comes from.
It's important that one remembers to take advantage of all the shortcuts available throughout the calculation of the matrix, such as only calculating the determinant once and storing it for later use.
Feel free to drop us an email if you need help or find something a bit unclear.
Please refer to the article Bump Mapping using CG for example code on implementing the tangent space matrix.

9. References

[1]  http://www.delphi3d.net/articles/viewarticle.php?article=phong.htm
Return to articles overview

Copyright © Blacksmith Studios 2006
