Sign in to follow this  

Normalizing normals in VS

Recommended Posts

I have seen VS omitting the normalization of the normal with the excuse of postponing the normalization to the PS. But how could this ever be correct?

If points are transformed with A, normals should be transformed with A^-T (the inverse transpose). The latter could have a determinant greater than 1 due to scale components. It is even possible to have a determinant of 1 due to non-uniform scale components (the latter will work since the matrix is applied to all three vertices). Assume we have a triangle with vertex normals (1,0,0), (0,1,0) and (0,0,1) and assume A^-T is just a non-uniform re-scaling of (1,2,3). The transformed normals are thus equal to (1,0,0), (0,2,0), (0,0,3). If we normalize in the VS, the final normals are again (1,0,0), (0,1,0) and (0,0,1). Assume now, we have a fragment with barycentric coordinates (0.33,0.33,0.33). If we normalized in the VS, the interpolated normal will be ((0.577,0.577,0577) after normalization in the PS). If we didn't normalized in the VS, the interpolated normal will be (0.33,0.66,0.99) ((0.267,0.534,0.801) after normalization in the PS).

This could only work by 'normalizing' your transformation matrix to have a determinant of 1. Otherwise the VS needs to do a normalization as well? (Maybe I only have bad examples at my disposal ;) )

Share this post


Link to post
Share on other sites

Non uniform scaling sucks in render engines in general, i don't have better to say :)

A normalize in the VS won't hurt performance, and the PS has to normalize because interpolation deviate from the lenght of 1 and the angular rotation speed over the surface is not constant (booo but no one care).

Soon to be fixed with shader model 6. Because you can fetch the barycentric coordinates, the 3 vertices and do a custom interpolation in the form of a slerp of 3 quaternion ( packing your tangent basis ).

Share this post


Link to post
Share on other sites

How could it not be correct considering that your VS output are interpolated so each fragment will received this interpolated value.  If you are transforming your normals with matrices having non-uniform scales or any scales for that matter is asking for trouble..ex..why doesn't my lighting looks correct. Rotation should be the only thing affecting your normals.

Share this post


Link to post
Share on other sites
Posted (edited)
1 hour ago, cgrant said:

How could it not be correct considering that your VS output are interpolated so each fragment will received this interpolated value.  If you are transforming your normals with matrices having non-uniform scales or any scales for that matter is asking for trouble..ex..why doesn't my lighting looks correct. Rotation should be the only thing affecting your normals.

If your scene graph applies non-uniform scaling, you'll have the problem anyway for your normals. You can only throw scale away if it is uniform. Otherwise, this will effect your normals as well.

Edited by matt77hias

Share this post


Link to post
Share on other sites
1 hour ago, galop1n said:

Non uniform scaling sucks in render engines in general, i don't have better to say :)

I see idd more disadvantages with non uniform scaling. If I was an artist, I would only use it for some basic objects like planes and cubes.

1 hour ago, galop1n said:

A normalize in the VS won't hurt performance,

So not worth the trouble of fixing on the CPU in the already bulky Transform classes

Share this post


Link to post
Share on other sites
2 hours ago, cgrant said:

If you are transforming your normals with matrices having non-uniform scales or any scales for that matter is asking for trouble..ex..why doesn't my lighting looks correct. Rotation should be the only thing affecting your normals.

He mentioned the fix for this: transforming normals with the inverse-transpose of the matrix used for positions corrects issues caused by non-uniform scaling. It basically inverts the scale -- normally if you squash a ball vertically this would also squish the normals vertically (which after renormalisation results in them being stretched horizontally), but, if you use the inverse-transpose, the normals are stretched vertically (which results in the correct behaviour of the top of the ball becoming flatter).

Lots of engines simply disallow non-uniform scaling though; perhaps they don't want to store a 2nd transform per object? 

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