Home » Community » Forums » Graphics Programming and Theory » Light vectors in tangent space
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 Light vectors in tangent space
Post New Topic  Post Reply 
I just recently got a GeForce FX card, and have been experimenting with shaders. I implimented some normal mapping the way it was presented in all the tutorials I read, which is to use tangent and bi-normal vectors to transform the normal from the map from tangent space to world space, and it worked just fine.

But transforming the normal this way every pixel seemed inefficient, so I tried doing the opposit: transforming the light and half vectors into tangent space, and doing it per-vertex, rather than per-pixel. It seems to work equaly well, it removes the normal transformation, and it passes 2 fewer parameters to the pixel shader.

Has anyone tried doing this before? Is there some fatal flaw I have yet to discover?

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Your method is the common way to do normal mapping in ps.1.1. In ps.2.0 and higher people seem to use the other method. It avoids the problem of having your tangent-space light vector being non-normalized.

Here I demonstrate the issue, which can be mostly fixed with a normalization cube map. Since this only "mostly" fixes it, and it requires an extra cube map texture lookup, is probably why the other method is preferred.

 User Rating: 1759   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Yes, you have rediscovered the way most folks have been doing it for quite a while! :)

As far as I know, Doug Rogers and I were the first people to develop the currently popular method of deriving smooth tangent spaces from texture coordinates & vertex normals back in the GeForce1/2 timeframe - and we did it like you say. Move the L vector into tangent space per-vertex and let the hw interpolate it.

Depending on how you generated the tangent space, and what type of vector you are interpolating it may or may not be 100% accurate.

In general, you definitely want to move linear or almost-linear computations to the vertex shader, and moving vectors into tangent space is certainly a good one to start with.


 User Rating: 1569   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Doing it that way is faster, but may lead to more interpolation error, especially across large or heavily bent surfaces, or objects close to the light source (with local light sources).

Also, you really don't want to take the light into the normal space -- you want to take the normal out of tangent space into model space, because then you can also use the vector for environment mapping. Where going one way is a series of DP3, going the other way is a series of MAD, so it's really no more expensive doing one vs the other (you don't need to transpose the matrix explicitly).

 User Rating: 1944   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Quote:
Original post by Namethatnobodyelsetook
Here I demonstrate the issue, which can be mostly fixed with a normalization cube map. Since this only "mostly" fixes it, and it requires an extra cube map texture lookup, is probably why the other method is preferred.

Don't you need to re-normalize the normal in the other method too?

Quote:
Original post by SimmerD
Yes, you have rediscovered the way most folks have been doing it for quite a while! :)

Yeah, I figured it must have been done before, but I had never seen it mentioned anywhere, which is why I thought there may be a problem I hadn't seen.


Quote:
Original post by hplus0603
Where going one way is a series of DP3, going the other way is a series of MAD, so it's really no more expensive doing one vs the other (you don't need to transpose the matrix explicitly).

Yes, but putting the light and half vectors into tangent space can be done in the vertex shader instead of pixel.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by SimmerD
As far as I know, Doug Rogers and I were the first people to develop the ...

Lindholm? Everitt? Ramey? Way off?


Anthony Whitaker
[Boanerges Studios] :: [RZ2 Games] :: [Exigent Game Art] :: [Personal Site] :: [GraphicsDev.net]

 User Rating: 1353   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Bagel Man
Quote:
Original post by Namethatnobodyelsetook
Here I demonstrate the issue, which can be mostly fixed with a normalization cube map. Since this only "mostly" fixes it, and it requires an extra cube map texture lookup, is probably why the other method is preferred.

Don't you need to re-normalize the normal in the other method too?

Yeah, that occured to me sometime after I posted. In truth, I've yet to use anything above ps.1.1 so I don't know the details of the other ps.2.0 method.

 User Rating: 1759   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Sages
Quote:
Original post by SimmerD
As far as I know, Doug Rogers and I were the first people to develop the ...

Lindholm? Everitt? Ramey? Way off?


If by Everitt, you mean Cass Everitt, yes he learned it from us when he started at nvidia. Not sure who you mean by Lindholm ( Erik? ) or Ramey ( Will? ), but Doug Rogers and I created devloped & tested the method in february '00, then popularized it inside of nvidia. Then I helped put it into Evolva, and the Whole Experience Demo. Those were fun times...

I remember as soon as Cass started I explained to him my 1-(x^2+y^2+z^2) attenuation map technique, and he came up with the gaussian method ( which is cooler in some ways )...


 User Rating: 1569   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Quote:
Original post by SimmerD


So (going out on a limb here) that makes you Sim Dietrich?
If so... it's a pleasure to be conversing with you and I was unaware of your presence in these forums. I should've paid more attention to your previous posts.


Anthony Whitaker
[Boanerges Studios] :: [RZ2 Games] :: [Exigent Game Art] :: [Personal Site] :: [GraphicsDev.net]

 User Rating: 1353   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Sages
Quote:
Original post by SimmerD


So (going out on a limb here) that makes you Sim Dietrich?
If so... it's a pleasure to be conversing with you and I was unaware of your presence in these forums. I should've paid more attention to your previous posts.


Likewise -- it's cool to see we have a few VIPs here

 User Rating: 1893   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Yep, that's me alright.

BTW, I just implemented blending tangent space normal maps as decals into my engine, and it works great. Doing this with object space seems like it would be much harder.

 User Rating: 1569   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Quote:
Original post by SimmerD
BTW, I just implemented blending tangent space normal maps as decals into my engine, and it works great. Doing this with object space seems like it would be much harder.

Yeah, this is really interesting stuff. I actually did the same thing a few weeks ago and would like to ask a few questions.

1) Are you only applying the normal map or do the decals also have other information (ie: diffuse, specular)?

2) Have you put any thoughts into using depth correction on the decal?

I hacked together a method to get depth correction working but I still have artifacts on corners and curves especially with larger depths. Overall the technique produces a really nice effect, however the method is not very practical or efficient. Any thoughts?


Anthony Whitaker
[Boanerges Studios] :: [RZ2 Games] :: [Exigent Game Art] :: [Personal Site] :: [GraphicsDev.net]

 User Rating: 1353   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by SimmerD
Quote:
Original post by Sages
Quote:
Original post by SimmerD
As far as I know, Doug Rogers and I were the first people to develop the ...

Lindholm? Everitt? Ramey? Way off?


If by Everitt, you mean Cass Everitt, yes he learned it from us when he started at nvidia. Not sure who you mean by Lindholm ( Erik? ) or Ramey ( Will? ), but Doug Rogers and I created devloped & tested the method in february '00, then popularized it inside of nvidia. Then I helped put it into Evolva, and the Whole Experience Demo. Those were fun times...

I remember as soon as Cass started I explained to him my 1-(x^2+y^2+z^2) attenuation map technique, and he came up with the gaussian method ( which is cooler in some ways )...


How cool is that, to actually talk (kind of) with one of the guys that developed tangent space bump mapping. I am humbled... :)

Jason Zink :: MVP XNA/DirectX
"Intellectuals solve problems, geniuses prevent them." - Albert Einstein
Check out my game: Lunar Rift :: Dual-Paraboloid Mapping Article :: Parallax Occlusion Mapping Article :: Fast Silhouettes Article
Check out our free online D3D10 book: Programming Vertex, Geometry, and Pixel Shaders

 User Rating: 1488   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Quote:
Original post by Sages
Quote:
Original post by SimmerD
BTW, I just implemented blending tangent space normal maps as decals into my engine, and it works great. Doing this with object space seems like it would be much harder.

Yeah, this is really interesting stuff. I actually did the same thing a few weeks ago and would like to ask a few questions.

1) Are you only applying the normal map or do the decals also have other information (ie: diffuse, specular)?

2) Have you put any thoughts into using depth correction on the decal?

I hacked together a method to get depth correction working but I still have artifacts on corners and curves especially with larger depths. Overall the technique produces a really nice effect, however the method is not very practical or efficient. Any thoughts?


Since I posted, I now have 2 methods for blending in materials. Method one involves a 2-layer material specified at design time. There is a uniquely textured RGBA texture across the world that contiains R : Diffuse blending factor, G : Normal blending factor, B : Ambient occlusion , A : Sunlight occlusion factor.

I do semi-deferred shading in the engine, so first I output diffuse to a buffer for all world surfaces, including 1 or 2 layer materials. Then I alpha blend in the decals' diffuse on top. Then I copy this to a texture.

Next is the same for the normals for the world surfaces ( in tangent space ), then alpha blend decals' normals, then copy offscreen. I just doa straight srcalpha,invsrcalpha blend, don't renormalize, and don't correct depth. Of course my view is mostly top down, so the depth is not much of an issue.

Then I do the ambient & occlusion & Z pass using the offscreen surfaces as screen-aligned projected textures, rendering the actual world geometry. This is why I call it semi-deferred shading in the sense that most folks render the light geometry instead of the world gometry. I prefer my method b/c it is still fast, and it uses a similar setup to the old-non-deferred path which I may have to revive for older drivers or slower machines. Also its the only way to do it without an accurate view-space Z for all surfaces ( which can't be reasonably done in ps.1.1 ).

Then, for each light, I have an index list of just the triangles that aren't statically shadowed from that light, and I render those, again using the offscreen diffuse & normal map buffers. I store gloss in normal.alpha, and am not using diffuse.alpha for anything yet, although I am considering either a fresnel or scattering term.

The cool thing is that all of this is done in vs & ps.1.1!
Maybe I'll start a thread on this rather than hijacking this one...


 User Rating: 1569   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: