Now let us see another point, more significant from the bump mapping implementation point of view than from the global
understanding of the bump mapping itself. It is about the vertex space more known as the tangent space. This space is in fact
a frame of reference attached to each vertex in which the position of the vertex is {0.0, 0.0, 0.0 } and the coordinates of the normal
vector to the vertex are {0.0, 0.0, 1.0 }.
The three vectors forming this orthonormal frame of reference are named tangent, binormal and normal with:
tangent vector = {1.0, 0.0, 0.0} or X axis
binormal vector = {0.0, 1.0, 0.0} or Y axis
normal vector = {0.0, 0.0, 1.0} or Z axis.
The things will start to become clear assuming that the normal vectors stored in the normal map are expressed in the tangent
space. This explains the bluish color of the normal-map because most vectors are directed along the Z axis. If the
normal-map was expressed in the frame of reference of the object, there would be vectors directed along the 3 axes of the object local
reference mark, which would lead to bluish, green and red zones.
Ok, if I talk about this, it is because the realization of a normal-map is easier when the normal vectors are expressed in the tangent
space. Moreover, most of the bump-maps creation tools use normal vectors in the tangent space (the nVidia plugins for
PhotoShop or the tool provided by ATI are good examples).
The problem is that the normal vector is expressed in the tangent space whereas the other vectors used for calculations (light and
view vectors) are expressed in another reference space (the camera space). It is thus necessary to express
all these vectors in the same single reference space so that calculations (mainly dot product) can have a meaning. This reference space
is the tangent space. The following matrix algebra shows how to pass the L light vector, expressed in the camera space, to the tangent
space:
|x| |Tx Ty Tz| |Lx|
|y| = |Bx By Bz| x |Ly|
|z| |Nx Ny Nz| |Lz|
Such a matrix calculus can be replaced by 3 dot products:
x = L dot T
y = L dot B
z = L dot N
where x, y and z are the coordinates of the light vector expressed in the tangent space and where the TBN vectors are expressed
in the camera space...
There is still a small detail to be cleared up. How do we get the T, B and N vectors for each vertex. For the N vector, no problem,
since it is the normal to the vertex provided by the 3d engine and may be found in the GLSL code as the as the gl_Normal vector.
The new thing is the T vector which is also provided by the 3d engine but as a vertex attribute (attribute key word in GLSL code).
Once we get the T and N vectors, B vector calculus is done by a cross product between T and N...
Update: December 30, 2006:
The following tutorial provides a method to compute the T and B vectors from N: Tangent Space Computing.
I think that the essence of the theoretical implementation of the bump mapping is clarified. It is time to go inside the GLSL code
for really understanding some-thing there...
fig.3 - The normal-map in the tangent space.