Wednesday, 16 April 2008

Tangent Space

Reading the article on tangent space has made a lot more things clear, especially:
1. how the lighting works when using vertices, and per-pixels.
2. What the RGB values correspond to, and how they are calculated for a normal map
3. and ofcourse, what a tangent space is.

This makes the shader program on relaxed cone step mapping of Fabio Policarpo much easier to understand, and I think in general, it will make the concept of shaders much easier for me. Well written article, easy to understand.

Summary:
Deriving World to tangent space transformation matrix:
u,v,n vectors are Tangent(T), Bi-normal(B), Normal(N).
Matrix for T,B,N:
Mwt = (Tx, Ty, Tz; Bx, By, Bz; Nx Ny Nz);
Same point in tangent space (Posts) will be
Posts = Posws x Mwt
Creating tangent space matrix for a face:
Step 1: Calculate any two edge vectors
Step 2: Calculate the T vector
Step 3: Calculate the normal vector (N)
Step 4: Calculate the Bi-normal vector (B)
Step 5: Build Mwc from T,B,N

Creating tangent space matrix for a vertex:
We need to split the matrix for each face, to each vertex that defines the face.
This is done by calculating the average of the vectors from all the faces that share that vertex.

Per-pixel lighting using pixel and vertex shaders:
Note: this is for bump mapping

The vertex shader - calculating the light vector
Step 1: Calculate the light vector, we assume that both the light position and the vertex position are in the world space coordinate system
Step 2: Convert the light vector from the world space coordinate system to a vector in the tangent space coordinate system. Assuming that you have already calculated the tangent space matrix for each vertex and passed it into the vertex shader via the texture channels, this is just a simple matrix multiplication.
Step 3: Normalize the light vector. This light vector is passed to the pixel shader in a previously decided texture stage. One very big advantage of doing this is that the light vector gets interpolated across the face for free.
Note: The interpolated light vector is no longer normalized when it reaches the pixel shader

Pixel Shader - calculating diffuse brightness for each pixel
Step 1: Get the light vector
Step 2: Get the normal at the texel
Step 3: Calculate the surface brightness
Step 4: Modulate with diffuse colour

Aside:
Why does a normal map always look blueish?
The z component of a surface normal at point never points backwards
Vn.z > 0.0
This results in
In.B > 127.5
Another point to remember is that a normal map is always encoded in the tangent space coordinate system instead of the world space coordinate system.


As the RGB values of normal maps are pretty clear, now onto changing normal maps to depth maps, then to cone maps in order to use with Fabio's relaxed cone step mapping shader program.

No comments: