Contents
Messing with Tangent Space
 
 
Printer-Friendly VersionPrinter-Friendly Version
 
Latest News
spacer View All spacer
 
November 22, 2009
 
Video Game Watchdog National Institute On Media And The Family Shutting Down [11]
 
Modern Warfare 2 Infinity Ward's 'Most Successful PC Version' Yet [12]
 
New Tech, Design Details Of Project Natal To Emerge At Gamefest In February
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
November 22, 2009
 
Trion Redwood City
Sr. Evnironment Modeler
 
Trion Redwood City
Sr. Environment Artist
 
Sucker Punch Productions
3D Environment Artist
 
Sucker Punch Productions
Network Programmer
 
Sucker Punch Productions
Character Artist
 
Sucker Punch Productions
Texture Artist
 
Monolith Productions
Sr. Software Engineer, Engine - Monolith Productions - #113767
 
Sony Online Entertainment
Brand Manager
spacer
Latest Features
spacer View All spacer
 
November 22, 2009
 
arrow Upping The Craft: Susan O'Connor On Games Writing [6]
 
arrow Small Developers: Minimizing Risks in Large Productions - Part II [7]
 
arrow iPhone Piracy: The Inside Story [48]
 
arrow And Yet It Grows: Analyzing the Size and Growth of the European Game Market [5]
 
arrow NPD: Behind the Numbers, October 2009 [13]
 
arrow Reflecting On Uncharted 2: How They Did It [5]
 
arrow Sponsored Feature: Rasterization on Larrabee -- Adaptive Rasterization Helps Boost Efficiency
 
arrow Postmortem: Wadjet Eye's The Blackwell Convergence [2]
spacer
Latest Blogs
spacer View All     Post     RSS spacer
 
November 22, 2009
 
Time Fcuk
 
Accepting the Inherent Value of Games
 
Planckogenesis, Part II: Song Structure & Gravy Train [1]
spacer
About
spacer News Director:
Leigh Alexander
Features Director:
Christian Nutt
Editor At Large:
Chris Remo
Advertising:
John 'Malik' Watson
Recruitment/Education:
Gina Gross
 
Features
  Messing with Tangent Space
by Siddharth Hegde
5 comments
Share RSS
 
 
July 16, 2007 Article Start Previous Page 2 of 7 Next
 

Why Use Tangent Space

Both, tangent space and world space represent a 3D space, just as inches and meters both represent length. If any meaningful calculations need to be done, all values must be in the same unit system or coordinate systems.

At this point you are probably wondering…

Advertisement

So why use tangent space in the first place? Why not just declare all positions and vectors in world space?

Certain per pixel lighting techniques and many other shaders require normals and other height information declared at each pixel point. This means that we have one normal vector at each texel and the n axis will vary for each texel. Think of it as a bumpy surface defined on a flat plane.

Now if these normals were declared in the world space coordinate system, we would have to rotate these normals every time the model is rotated even a small amount. Remember that the lights, camera and other objects also involved in these calculations will be defined in world space and will move independent of the object. This would mean thousands or even millions of object to world matrix transformations will need to take place at the pixel level. We all know matrix transformations don't come cheap.

Instead of doing this, we declare the thousands of surface normals in the tangent space coordinate system. Then we just need to transform the other objects (mostly consisting of lights, the camera, etc) to the same tangent space coordinate system and do our calculations there. The count of these objects won’t exceed 10 in most cases.
So it’s 1000000s vs 10s of calculations. Hmmm… It’s going to take a while to decide which one would be better.

Think of the box in figure 2 rotating. Even if we rotate it, the tangent space axis will remain aligned with respect to the face. Then instead of converting thousand or millions of surface normals to world space we convert tens or hundreds of light/camera/vertex positions to tangent space and do all our calculations in tangent space as required.

To add to the list of advantages of tangent space, the matrices required for the transformations can be pre calculated. They only need to be recalculated when the positions of the vertices change with respect to each other.

Hopefully you understand why we need tangent space and a transformation from world space to tangent space. If not, for now think of it as something that we just need to have and you will begin to understand when you read the second section.

3. Deriving a World space to Tangent space transformation matrix

In order to convert between coordinate system A to coordinate system B, we need to define the basis vectors for B with respect to A and use them in a matrix.

What are basis vectors?

Every n-dimensional coordinate system can be defined in terms of n basis vectors. A 3 dimensional coordinate system can be defined in terms of 3 basis vectors. A 2 dimensional coordinate system can be defined in terms of 2 basis vectors. The rule is that every vector that makes up a set of basis vectors is always perpendicular to the other basis vectors.

It’s basically one of those fancy mathematical terms given to three three vectors (in a 3D world) of unit size and perpendicular to each other. These three vectors can point in any direction as long as they are always perpendicular to each other. If you would like to visualize a set of basis vectors, think of an axis drawn in any 3D application. Look at Figure 1 & 2. The vectors that are on the axis (x, y, z) define one set of basis vectors. The vectors u, v, n also define another set.

Method of deriving world to tangent space transformation matrix

And why all the fuss over these basis vectors?
In order to achieve our goal, the first step is to define the u, v and n basis vectors in terms of the world space coordinate system. Once we do that, the rest is just a cakewalk.

From here on, I will refer to the u, v, n vectors as the Tangent (T), Bi-Normal(B) and Normal (N). Why? Because this is what they are actually called.

As I said before we need to find the T, B, N basis vectors with respect to world space. This is the first step in the process.

A simple way of thinking of this would be:
I have a vector that points in the direction in which the u value increases across a face, then what will be it’s value in the world space coordinate system.

Another way of thinking of it would be:
To find the rate of change of the u, v, n components across a face with respect to the x, y, z components of world space. The T vector is actually the rate of change of the u component with respect to world space.

Whatever way you choose to visualize it in, we will have the T, B, N vectors.
The next step is to build a matrix of the form:

 

Tx

Ty

Tz

Mwt =

Bx

By

Bz

 

Nx

Ny

Nz

Multiplying a world space position (Posws) with Mwt will give us the position of the same point in terms of tangent space (Posts)

Posts = Posws X Mwt

As mentioned before the T, B, N vectors (and all basis vectors) will always be at right angles to each other. All we need to do is derive any two vectors and the third will be a cross product of the previous two. In most cases, the face normal will already be calculated. This means we just need one more vector to complete our matrix.

Creating the tangent space matrix for a face

In this section I will take a single face and then derive Mwt for the face.

Figure 3: A sample face

Let’s assume the vertices of the face in Figure 3 have the following values

Vertex

Position (x, y, z)

Texture coordinate (u, v)

V1

(0, 20, 0)

(0, 0)

V2

(20, 20, 0)

(1, 0)

V3

(0, 0, 0)

(0, 1)


As stated in the previous section,

  1. The tangent vector (u axis) will point in the direction of the increasing U component across the face.
  2. The bi-normal vector (v axis) will always point in the direction of increasing V component.
  3. The n component is always assumed to be constant and hence is equal to the normal vector (n axis), and will point in the same direction as the face's normal.

In order to derive T, B, N calculate the difference of the u, v, n components across the face with respect to the x, y, z components of world space.

Step 1: Calculate any two edge vectors. Edge

E2-1 = V2 - V1 = (20-0, 20-20, 0-0) & (1-0, 0-0) = (20, 0, 0) & (1, 0)
E
3-1 = V3 - V1 = (0-0, 0-20, 0-0) & (0-0, 1-0) = (0, -20, 0) & (0, 0)

Edge E2-1 and E3-1 is actually the difference of x, y, z and u, v components between V1, V2 and V1, V3

Step 2: Calculate the T vector

In order to get the tangent vector T we need the rate of change the x, y, z components with respect to the u component.
Hence:

T = E2-1.xyz / E2-1.u = (20/1 , 0/1 , 0/1) = (20, 0, 0)

The T vector is then normalized. This is done because we do not need the scalar component of the T, B, N vectors.

T = Normalize(T) = (1, 0, 0)

Note: This works fine for E2-1 in this case, but what if the E2-1.u was equal to 0. There is a good chance that this can happen, depending on how your artist has mapped the mesh. If the value of E2-1.u value is 0, then we perform the same calculation on E3-1. It does not matter which edge we use, all we are looking for is the direction of increasing u component across the face.

Step 3: Calculate the Normal vector (N)

Now that we have the tangent vector, we can get the N vector. This is a standard calculation for a face normal that we normally do.

A simple cross product of the edge vectors E2-1 and E3-1 can get us the face normal.

N = CrossProduct(E2-1 , E3-1) = CrossProduct ( (20, 0, 0) , (0, -20, 0) ) = (0, 0, -400)
And just as with the T vector, N is also normalized.

N = Normalize(N) = (0, 0, -1)

Step 4: Calculate the Bi-Normal vector (B)

As mentioned earlier the T, B, N vectors are always at right angles to each other, hence we can derive the third from by just doing a cross product of the previous two. Therefore

B = CrossProduct ( T , N ) = CrossProduct ( (1, 0, 0) , (0, 0, -1) ) = (0, 1, 0)

Step 5: Build Mwt from T, B, N

Now that we have T, B, N, we can build Mwt

 

Tx

Ty

Tz

=

1

0

0

Mwt =

Bx

By

Bz

0

1

0

 

Nx

Ny

Nz

0

0

-1

And volla! There we have our matrix.

 
Article Start Previous Page 2 of 7 Next
 
Comments

Kiran Sudhakara
profile image
Step 2: Calculate the T vector
T = E2-1.xyz / E2-1.u

This formula does not seem correct. Wouldn't this just scale the edge?

David Larsson
profile image
Responce to Kiran's comment:

I think the formula is supposed to be more like this(could be wrong though):

NE2-1 = Normalize(E2-1)
NE3-1 = Normalize(E3-1)
T = (NE2-1.xyz / E2-1.u) + (NE3-1.xyz / E3-1.u)

Kiran Sudhakara
profile image
Unfortunately I believe this is wrong aswell. Consider a simple case where E2-1.uv is 1,0 (so E2-1.xyz is already the tangent!), and E3-1.uv is an angled vector across the UV space.

Shih-Kai Lai
profile image
http://www.terathon.com/code/tangent.html
http://www.blacksmith-studios.dk/projects/downloads/tangent_matrix_derivation.ph
p

These 2 website have good explanations about tangent space.

Does any body know, if 2 vertex of a triangle have the same UV, then should I ignore that triangle, or ask art to change the UV? The determinant will become 0 in this case...

Julian Hainsworth
profile image
No two vertices should have the exact same UV-Coords, if this is a problem with your meshes you should see your artist


none
 
Comment:
 


Submit Comment