How to correctly generate tangent-space normal maps

Introduction

I started by reading a GDC presentation which lead me into thinking that most normal maps were generated all wrong because the “intuitive” way is not the right one.

The presentation states that if you make your normal map in Photoshop and then save it as a DDS, or as any other format, the mip maps that are generated are wrong on two aspects :

  1. They aren’t normalized, which means the normals have a length greater or lesser than 1;
  2. They do not represent the height of the surface at its mip level.

But nVidia thought about this and made a function into their DDS exporter which allows correct generation of normal map mip maps, where all the mip maps are generated from the height data at the same mip level. Also, it takes advantage of Photoshop’s filtering to get the most accurate results.

The presentation also claims that this workflow is more natural anyway, and doesn’t involve filtering the texture before before exporting it, as the DDS exporter does everything for you.

I say “claims” like I intend to reject them... but it works very well indeed! That means you can keep your height maps as PSD Photoshop files, and export the DDS that contain normal data. If you need to tweak the amplitude or other settings of the normal map, you can do so easily by re-generating the DDS from the height data, keeping all the precision.

The details

What you're probably doing, and should not do

The usual and wrong way of creating normal maps is as follows :

  • Create the height data, or use texture data to derive it;
  • Use NormalMapFilter (shown below) to make an normal map out of the height data;

  • Export to DDS or to any other image format, optionally encoding mip maps in it.

What you should do

The simpler and right way of creating normal maps is as follows :

  • Create the height data, or use texture data to derive it;
  • Directly export to DDS like shown below, auto-generating the normal map :

Simply said...

So what you need to do in the exporter to make that work :

  • Check the “Generate Mip Maps“ radio button and set the combo box to “All"
  • Click on “Normal Map Settings"
  • In the dialog, check “Convert To Tangent Space Normal Map"

Comparisons

So that’s all fine, but does it really make a difference? A question I asked myself...

Theoretical test

Here’s the comparision of a wrongly mipmapped normal map (left), and correctly mipmapped normal map (right), from the same height data. I made all sorts of bumps in it, high-frequency noise, lower frequency one, some clouds, some small bumps, etc. so you can see the real effect. Compared in ATi’s “The Compressonator”, the differences were then contrast-augmented :

Mip Level 0 : Obviously no differences
Mip Level 1 : The lack of normalization in the wrong (left) version is obvious in high-frequency details.
Mip Level 2 : The high-frequency parts fade to gray!
Mip Level 3 : More of the same, and also look at the “Te” letters, the wrong version has bumps way too high, compared to the right version which is the reference.
The rest of the levels was more of the same.

In the real world

Yeah ok, but these were extreme cases. In real life, is it worth it?

Hard question. I tried it in my water sample and found absolutely no visual difference. Even on still-frame evaluation.

It’s more a question of what workflow works better for you. But, knowing it does make a difference in some cases, I’d hate to use the “wrong” workflow since it might introduce artifacts...

That was all. Thanks for reading, and get Photoshopping! ;)

 
tutorialsarticlesandexamples/how_to_correctly_generate_tangent-space_normal_maps.txt · Last modified: 2013/11/22 13:32