Tangent space is basicaly used for advanced rendering techniques such as normal
mapping.
Briefly, normal mapping is a per pixel normal technique which is based on
pixel's normal perturbation. Normals for each pixel are stored in as rgb picture called normal map.
The normal is applied to the pixel in a similar way than for the color with the
diffuse texture. The uv texture coordinate
of the pixel is used for reading in the normal map for getting the pixel's normal.
This is the normal used for light computation on this pixel (per-pixel
lighting).
This
normal is stored in this map in the tangent space coordinate system.
Tangent space is a coordinate system attached to a
planar surface. The surface commonly used is a triangular shape. Tangent space
transformation convert a vector from the world space into a vector in texture
space.
In the above example, pixel normal is stored in texture space. Tangent space can
be used to convert this normal in world space for light computation. Generaly,
the inverse is done ie converting vectors used for light computation into
tangent space ('texture' space) and do the lighting computation in texture
space.
Tangent space is composed of 3 vectors (T, B, N) respectively
called tangent, binormal and normal. Tangent and binormal are vectors in the
plane. While normal vector is perpendicular to the place, so it is also
perpendicular to tangent and binormal vectors.
In the texture space, (T, B) vectors correspond to (u, v) vectors. This means, T
is the vector (1, 0) in texture space and B is the (0, 1). This is the
coordinates of T and B in texture space.
You can see a representation of (T, B, N) coordinate system in both texture and
world space. The picture was
From Matyas Premecz's paper [1]
The tangent space transformation convert a point expressed in world space ie (x,
y, z) to a vector in texture space (u, v, w).
Tangent space is really usefull for advanced rendering texhnique which stores
pixels information (normal, height, color ...) in a texture. Tangent space allow
working directly in texture coordinate system
Suppose a point p_{i} in world coordinate system for
which texture coordinates are (u_{i}, v_{i}), the relation
between texture coordinates (ie ui u_{i}, v_{i}) and world space
(p_{i}) is govern by the relation .
Note: This point can also be considered as the
vector starting from the origin to p_{i}.
p_{i} = u_{i}.T + v_{i}.B
Texture/World space relation
Writting this equation for the points p1, p2 and p3 give :
p_{1} = u_{1}.T + v_{1}.B
p_{2} = u_{2}.T + v_{2}.B
p_{3} = u_{3}.T + v_{3}.B
With equation manipulation (equation subtraction), we can write :
p_{2} - p_{1} = (u_{2} - u_{1}).T
+ (v_{2} - v_{1}).B
p_{3} - p_{1} = (u_{3} - u_{1}).T + (v_{3}
- v_{1}).B
By resolving this system :
(v_{3} - v_{1}).(p_{2} - p_{1}) =
(v_{3} - v_{1}).(u_{2} - u_{1}).T + (v_{3}
- v_{1}).(v_{2} - v_{1}).B
- (v_{2} - v_{1}).(p_{3} - p_{1})
- (v_{2} - v_{1}).(u_{3} - u_{1}).T - (v_{2}
- v_{1}).(v_{3} - v_{1}).B
(u_{3} - u_{1}).(p_{2}
- p_{1}) = (u_{3} - u_{1}).(u_{2}
- u_{1}).T + (u_{3} - u_{1}).(v_{2} - v_{1}).B
- (u_{2} - u_{1}).(p_{3} - p_{1})
- (u_{2} - u_{1}).(u_{3} - u_{1}).T
- (u_{2} - u_{1}).(v_{3} - v_{1}).B
And we finally have the formula of T and B :
(v_{3} - v_{1}).(p_{2} - p_{1})
- (v_{2} - v_{1}).(p_{3} - p_{1})
T = ---------------------------------------
(u_{2} - u_{1}).(v_{3} - v_{1})
- (v_{2} - v_{1}).(u_{3} - u_{1})
(u_{3} - u_{1}).(p_{2}
- p_{1}) - (u_{2} - u_{1}).(p_{3} - p_{1})
B = ---------------------------------------
(v_{2} - v_{1}).(u_{3} - u_{1})
- (u_{2} - u_{1}).(v_{3} - v_{1})
Equation of tangent and binormal vectors
(T, B, N) is a base for the coordinate system. N can be obtained as the cross product of T by B :
N = cross(T, B)
Equation of normal vector
Tangent
Binormal
Normal
(T, B, N) form an orthonormal basis in texture space ie vectors
are unit length and are all perpendicular between each other.
However, the transformation from the texture space into world space is not
distance/angle conservative. So, generally, (T, B, N) is not orthonormal in
world space. This means T and B are not necessarily perpendicular, but they are
perpendicular with N. As well, these vectors are not necessary unitary.
The transformation matrix from is composed (T, B, N) vector in collumns :
TBN matrix
To transform a vector exprimed in world (object) space to a vector in tangent space, just multiply the matrix with the vector :
V_{World} = TBN V_{Tangent = }V_{Tangent}^{T
}TBN^{T}
Tangent space to world space
V_{Tangent} = TBN^{-1} V_{World = }V_{World}^{T
}TBN^{-T}
World space to tangent space
Those expressions can written like this :
[x y z]^{T} = TBN [u v w]^{T}_{ = }
[u v w]^{ }TBN^{T}
Tangent space to world space
[u v w]^{T} = TBN^{-1} [x y z]^{T}_{
= }[x y z]^{ }TBN^{-T}
World space to tangentspace
The Java & GLSL code come from my
Bonzai Engine project.
The Java source code uses some classes which is not detailled here, but I thinks
that is easy understandable. The related documentation can be found in the
Bonzai Engine project
homepage.
Here is the java code that calculates to tangent, binormal and
normal vector of a triangular face.
The Face object stores the definition of the traingle: the 3 vertices & their associated texture coordinates.
The output is written to the 3 vectors tangent, binormal and
normal vectors.
Tangent, binormal and normal vectors of a triangle |
public static void computeFaceTBNBasis(/*Mesh
mesh, */Face face, Vector3f tangent,
Vector3f binormal, Vector3f normal) |
As noticed previously, the tangent and binormal vectors are not ensured to be
perpendicular. Also, if normals are smoothed over faces, so the perpendicularity
with tangent will be lost. Due to this, we do a Gram-Schmidt orthogonalization
follow by a cross-product.
The orthogonalization is done between the tangent and normal vectors. Now, the binormal can be easily calculate with a cross product. Before doing this, we
check if the TBN space is right or left handed. The TBN space can be left handed
in the case of mirrored texture coordinates (see ... & the
screenshot section). If the TBN space is left handed, we just invert the
computed binormal to regenerate a left handed system.
Orthogonalization of TBN space |
//Compute TBN vectors |
To use the TBN space in a GLSL Shader, first we have to send the vectors like shown underneath :
Send Tangent space to GLSL shader |
/* |
Now, the TBN space in the GLSL shader code :
GLSL Vertex Shader |
attribute vec3 tangent; |
In the next screenshot, we can view the TBN space smoothed by
vertex (TBN space averaged over adjacent faces).
Note: The TBN smoothing for right & left handed
space are made separatly.
In the right side of the picture, the TBN space is right handed. The left side
of the model, the texture is mirrored (ie with mirrored uv). Due to this, the
TBN space is left handed. We can see the clear separation at the middle.
TBN Space with Mirrored UV
T is displayed in red
B is displayed in green
N is displayed in blue
More screenshots in Project 4 : Shaders.
This article was written thanks to some really usefull and interesting informations from this paper. I strongly encourage you to read it.
[1] Iterative Parallax Mapping with Slope Information, written by Matyas Premecz
Next Lesson |
Last modified on 01/07/2010 | |
Copyright © 2004-2012 JÃ©rÃ´me JOUVIE - All rights reserved. | http://jerome.jouvie.free.fr/ |