# Convert Normal from Tangent to World space

This topic is 4170 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, in my pixel shader, I have the normal of a fragment in world space that is passed from the vertex shader (vNormalWS), and I have a normal in tangent space that I read from the NormalMap texture (vNormalTS). How can I convert the vNormalTS to world space so I can do a cube map texture lookup? Thanks, Christian

##### Share on other sites
Eric Lengyel's book covers the maths behind it, but from a quick glance you can just transpose the matrix to get a Tangent->Object transformation:

| Tx Bx Nx || Ty By Ny || Tz Bz Nz |

Presumably a regular inverse transpose world transform should take it from Object->World.

hth
Jack

##### Share on other sites
Thank you, I also thought about using a tangent-to-world-space matrix. But it seems very expensive for a pixel shader operation. I have to compute the tangent and the binormal first, because they are not provided by the vertex shader. Then I have to create a matrix and multiply the normal with the matrix. Isn't there any easier way, where the tangent-space normal is used to alter the world-space normal?

##### Share on other sites
Quote:
 it seems very expensive for a pixel shader operation
Agreed - but thats probably why most people implement it in the opposite direction and at a coarser level (the VS) [smile]

You can convert a few vectors from world->tangent (relatively cheap) or you can convert every pixel from tangent->world (relatively expensive) - just depends which direction on the one:many mapping you want to go.

I'm sure you must be able to do some, or part, of the transformation at the vertex level. Determine the cube-map coordinate each each vertex and then pass this off to the PS for interpolation, then use the normal to perturb the interpolated coordinate (or something to that effect).

hth
Jack

##### Share on other sites
Quote:
Original post by jollyjeffers
Quote:
 it seems very expensive for a pixel shader operation
Agreed - but thats probably why most people implement it in the opposite direction and at a coarser level (the VS) [smile]

Yes, I also do calulate the vNormalWS (normal in world space) in the vertex shader in order to use hardware interpolation.
But the vNormalTS (tangent space normal) is read from a normal map texture in the pixel shader. I need to combine them to do the environment map lookup. So, to restate my original question, is this possible without knowing the tangent and the binormal?

##### Share on other sites
I found a solution in this Gamasutra article: Let There Be Light!
They transform the tangent space normal to world space just like you said:

Is this really the way to go? It's a pretty time-consuming calculation and I have to additionally pass the tangent from the vertex shader to the pixel shader.

##### Share on other sites
It would seem that you may have to do it the long-way as I suggested and the article backed up.

The main alternative is to "think outside the box" - try and determine which parts of the equation are really necessary, possibly try and write out all the calculations long-hand and see if you can simplify/approximate/factorise.

A while back I was using procedural/cubic equations in a VS and spent a bit of time multiplying out all the equations on paper and managed to elminate a few duplicate terms and knock a fair number of instructions off my shader. Same with when I manually implemented bilinear filtering.

You could also look at cube-maps. Is there any way that you can use vNormalWS and/or vNormalTS to index into a 1D/2D/3D map that then provides you with the correct lookup into the environment map? Doing this might allow you to offload some of the expensive calculations to the CPU and trade it in against a bit of added storage and a dependent texture read.

One last thing that you could consider - look into gradient instructions in ps_3_0 if possible. I've not checked it out, but it was suggested to me a couple of days ago as a way of skipping TBN generation entirely.

hth
Jack