Sign in to follow this  
mmikkelsen

initiative for a rock solid tangent space implementation standard.

Recommended Posts

Jason Z    6436
Thank you for contributing - this is a great initiative.

Is the thesis material available to the public? I would be interested in reading through it to see what the new method is doing that other methods don't do already.

Share this post


Link to post
Share on other sites
mmikkelsen    236
[quote name='Jason Z' timestamp='1306052969' post='4814158']
Thank you for contributing - this is a great initiative.

Is the thesis material available to the public? I would be interested in reading through it to see what the new method is doing that other methods don't do already.
[/quote]

Yeah it is though this implementation is not the exact same as in the thesis. This is geared more towards games in terms of various choices (than the thesis was).
For instance unlike the thesis I have chosen the transformation at pixel level to be as efficient as possible as described here
--> [url="http://wiki.blender.org/index.php/Dev:Shading/Tangent_Space_Normal_Maps#Pixel_Shader_Transformation"]http://wiki.blender...._Transformation[/url]

The thesis is here --> [url="http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf"]http://image.diku.dk...ikkelsen.08.pdf[/url]
Most of it is somewhat academic though since the intended audience was professors :)
I don't discuss the issues of index list or degenerates in the thesis but other then that the accumulation and order-dependency part (and how to deal with it)
is described in section 3.3

I also thought I'd show you guys some pictures to illustrate my motivation for doing this work. Most programmers don't realize how
problematic it is for artists to hide these issues: So I'll attach some examples of what problems might look like before they've gone through the trouble of hiding them best they can.

The ingame shot is of course a screen shot from doom 3. The other pictures are examples of issues where a professional artist has used commercial products
and run into these classic problems of unwanted hard edges. I also want to make it 100% clear this is not just an issue with mirroring.
This is an issue anywhere you have a tangent space split but you want smooth transitioning normals. This is a classic problem with characters
especially because you expect the normals to be smooth all over but splits are required to unwrap the model.

It's a pain for artists to hide this and they get seams between the fingers and have to hide seams on the head at the hair line, under hats etc.
The previous company I worked for used bald men mostly in their games :) So I had to listen to plenty of sob stories :)

The picture depicting an order-dependency is also interesting because it shows a perfectly mirrored triangular model. But the implementation he was using
had an order-dependency which resulted in the mirrored tangent space not always getting correctly mirrored. They were using the exact inverse transformation
in the pixel shader but because the normal map was mirrored this only gave them seamless results on the side that the normal map was baked to.
An order-independent implementation gives seamless results on both sides.

Share this post


Link to post
Share on other sites
mmikkelsen    236
Just thought I'd try to make it 100% clear why these unwanted hard edges occur.

As the baker transforms the normals sampled in object, world or view space into tangent space.
The baker uses some internal tangent space generation algorithm that will not produce the same spaces
as your pipeline does. Additionally, their implementation for transforming the interpolated tangent frame is almost certainly
not going to be the exact inverse of your pixel shader transformation out.

These two problems result in the normal you end up with in your pixel shader (after transforming it out of tangent space) will
deviate from the original captured normal. This is NOT a problem when tangent space is shared at a vertex because
the error will transition continuously from one face to the adjacent face. The problem occurs whenever there's a tangent space
split and the normals are supposed to be smooth. Because then the previously described error will not be the same on
both faces sharing the edge. This is why you get an unwanted hard edge in your lit result.

To fix it you have to be very pedantic and make sure the baker transforms the captured normal into tangent space using the exact inverse
transformation of your pixel shader. This includes making sure the exact same tangent spaces are given at the vertices.

So as I explained this problem is not specific to mirroring. Mirroring is just a special case that results in tangent space splits.
There is no way out of the need for tangent space splits. All we as programmers can do is fix our math by ensuring the baker uses the exact inverse
(and that we have no order-dependencies).

Share this post


Link to post
Share on other sites
maya18222    194
Hi,

I did try and read your thesis, but 99% of it was over my head. (I was wondering why you didnt use the transpose for the inverse tangent matrix)

Have you done any research into normal mapping using heightmaps with triangular meshes, and not requireing a tangent basis? This seems like the way to go, as I think it would solve so many problems. Less memory for tangents, less memory for normal map channels etc etc

I gather the problem is in computing the tangent basis in the pixel shader. One idea i had, which might not lead anywhere, was to create the tangent basis in the pixel shader by using the common

X = normal x up
Y = normal x X
Z = normal

this creates a correct tangent basis (in most cases), but just incorrectly rotated around the Z. If you knew this was how the tangent basis was going to be calculated, couldnt you preprocess the mesh, based on the UVS direction to the above tangent basis, and figure out how much rotation would be needed to correctly rotate this basis in the shader. Saving that rotation amount as an element in the vertex, and then rotating the basis by the appropiate amount in the shader?

Share this post


Link to post
Share on other sites
mmikkelsen    236
>I did try and read your thesis, but 99% of it was over my head. (I was wondering why you didnt use the transpose for the inverse tangent matrix)

Very simple. The baker has to use the exact inverse of what the pixel shader is using as I have explained. And people want their pixel shaders to be fast so they just use
vNout = vT*n.x + vB*n.y + vN*n.z;
to get their normal out of tangent space. So for the baker to be compliant you have to use the exact inverse of that since you have to do the exact inverse of whatever is done in the pixel shader.

>Have you done any research into normal mapping using heightmaps with triangular meshes, and not requireing a tangent basis?
> This seems like the way to go, as I think it would solve so many problems. Less memory for tangents, less memory for normal map channels etc etc

You mean something like this technical paper on bump mapping (check author name)? :) --> [url="http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf"]http://jbit.net/~spa...sfgrad_bump.pdf[/url]

>I gather the problem is in computing the tangent basis in the pixel shader. One idea i had, which might not lead anywhere, was to create the tangent basis in the pixel shader by using the common


This is not a good idea. You'll get terrible singularities using such a constant up vector which will look like terrible distortions in the normal map and the filtered result will be affected.
You also have to avoid creating discontinuities in tangent frame between triangles which are adjacent in the texture to avoid filtering seams.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this