• Advertisement
Sign in to follow this  

Normal Maps and Deferred Lighting

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I'm trying out the deferred lighting thing. I am keeping track of a color buffer, a depth buffer and a normal buffer. I'm storing all of the normals in eye-space so this leads to needing to transform the normals from normal maps from tangent/texture space into eye-space. I did some digging around and found that maybe the transpose of the NBT matrix would transform it but I'm getting strange results. I'm new to tangents and binormals anyway. I'm creating the tangents by a cross product with the normal and a vector from the vertex to the "next" vertex. This means all the tangents for each vertex on any given face will be rotated every which way. I wasn't sure if this matters or not. Anyone have guidance here?

Share this post


Link to post
Share on other sites
Advertisement
Hi there,

This is how I do it:

- So in the shader, you need the worldView matrix

- In vertex shader, transform tangent, binormal, and normal matrix into view space

- In pixel shader:

* Sample normal from normal maps and convert it to [-1,1] interval

* Transform it to view space by multiply with TBN matrix in view space

* Use view space normal computed above for lighting.

Here are some shader codes:


uniform extern float4x4 mWorldView;

Vertex shader:

// Transform TBN to view space
TBN[0] = mul(tangentL, gWorldView);
TBN[1] = mul(binormalL, gWorldView);
TBN[2] = mul(normalL, gWorldView);


Pixel shader:

// Sample normal map and transform it to view space
float3 normalT = tex2D(NormalMapS, TexCoord);

// Expand from [0, 1] compressed interval to true [-1, 1] interval.
normalT = 2.0f * normalT - 1.0f;

// Transform normal to view space
float3 viewNormal = mul(normalT, TangentToViewMatrix);



For creating tangent, binormal and normal, I load the model first, then use D3DXComputeTangentFrameEx() to calculate TBN. That's for DX9, but I figure OpenGL or higher DX should have the same function. Hope it helps.

Share this post


Link to post
Share on other sites
Switching from NBT to TBN helped out a lot. Thanks.

But now it looks like the normal map is rotated differently on different faces. Is this a result of the tangents and binormals going in different directions? How do I fix this?

Share this post


Link to post
Share on other sites
Ok. So the first image shows the object (a boulder) with it's non-transformed normal map. (Any seams that exist are because I'm a lazy modeler)

Plain Normal Map

The second image shows the normals after they have been transformed by the TBN matrix. I'm really confused that it wasn't the inverse of TBN that I needed but whatever, this is looking close.

TBN Transformed

So it looks like a bunch of new seams are appearing. I AM interpolating the tangents and binormals across the face. Is this wrong? Should I have the same tangent and binormal for the whole face? The models have per-vertex normals to make them look smooth.

Share this post


Link to post
Share on other sites
So I tried changing the model so that the tangent vector would be the same for each vertex (the binormal is derived from the normal and tangent in the vertex shader) and I think it improved. But my TBN matrix is no longer orthonormal so I still have some seam problems. Can you just not use per-vertex normals when you're doing bump mapping?

Non-orthonormal TBN transform

Share this post


Link to post
Share on other sites
Hi,

- First of all, the reason you don't need inverse of TBN because inverse of TBN is used in forward rendering to bring light direction to texture space so it can be used with normal from texture maps. Since we do it in view space, both light direction and normal will be transform to view space, and there is no need for inverse of TBN.

- For your problem, I just tumble upon this thread:

http://www.gamedev.net/community/forums/topic.asp?topic_id=468836

Seem like there will be some useful information for you. Also, which API are you using ? If you use DX, then there is function that does all the TBN calculation for you. Hope it helps.

Share this post


Link to post
Share on other sites
Thanks b_thangvn for that link. Generating the tangent with the uv coordinates makes so much sense but it was escaping me. It's all working great now. It's OpenGL by the way.

Share this post


Link to post
Share on other sites
Quote:
Original post by b_thangvn
Hi,

- First of all, the reason you don't need inverse of TBN because inverse of TBN is used in forward rendering to bring light direction to texture space so it can be used with normal from texture maps. Since we do it in view space, both light direction and normal will be transform to view space, and there is no need for inverse of TBN.


Now you're confusing me.
Everywhere I've looked, the tbn matrix is supposed to transform from object space into view space:

like here:
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter08.html
http://jerome.jouvie.free.fr/OpenGl/Lessons/Lesson8.php
http://www.gamedev.net/community/forums/topic.asp?topic_id=555834

Share this post


Link to post
Share on other sites
Quote:
... because inverse of TBN is used in forward rendering to bring light direction to texture space


in the link I provided, the 'standard' tbn matrix is use to 'bring light direction to texture space' not the inverse of tbn

I've always supposed that if you want to do normal mapping in view space then you're supposed to inverse the tbn matrix. But now b_thangvn is telling the opposite. That's why I'm confused.

Share this post


Link to post
Share on other sites
That's where I don't understand.

I use tbn to convert my light vector into tangent space, and the result is correct !

Is there more than one type of tangent/bitangent ? or is there a reason why both can be valid ? or else I'm just blind ?

Share this post


Link to post
Share on other sites
Quote:
Original post by flaviusxvii
I am using the TBN matrix to convert normals from a normal map (which are in tangent space) to eye space.


Quote:
Original post by SylHar
I use tbn to convert my light vector into tangent space, and the result is correct !

Is there more than one type of tangent/bitangent ? or is there a reason why both can be valid ? or else I'm just blind ?


You are probably using then transpose of each others matricies.

The reason is that the TBN matrix is an rotation matrix. And the inverse of an rotation matrix is the same as the transpose of that same matrix.

if TBN =
T1 B1 N1
T2 B2 N2
T3 B3 N3

rotates a vector from tangent space to object space then

Transpose(TBN) =
T1 T2 T3
B1 B2 B3
N1 N2 N3

rotates a vector from object space to tangent space

[Edited by - AndreasL on December 11, 2009 6:20:22 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement