This app demonstrates some ways in which mip-mapping and texture filtering in general might affect the quality of your normal maps. This subject came up in a conversation recently and while it is clear that the process of blending several unit vectors together doesn't result in a unit vector, I wanted to code this up in order to give a clear visual on how this might impact the look of your graphics if you don't pay it any attention.
For this demo I created a simple heightfield and from this I then generated two different normal map textures. The first, AutoMipped.dds, is the result of generating the full resolution normal map and then auto-generating the rest of the mip levels inside the DirectX Texture Tool. The second texture is FromHeight.dds - for this I generated each mip level by first downsampling the original heightfield and then generating a normal map from that. For this demo I also implemented three slightly different ways of getting the normal in the pixel shader.
In the first technique I simply use the normal sample directly as it comes from the texture sampler. When using the AutoMipped.dds texture the result is predictably flat and when using the FromHeight.dds texture the result is better but still more subdued than it should be.
This leads to the second technique where we normalize the filtered sample we are getting from the normal map. Here we can see the specular kick in quite a bit more for both textures.
For the third technique I simulate a not uncommon memory optimization - presuming our z-value to be >= 0, allowing us to store just the x & y values since we can recover the z value in the pixel shader. Here the results for AutoMipped.dds again become very flat - remember that we are recovering the z from x & y, however because of the filtering reducing the magnitude of our samples we end up effectively pushing all of our pixel normals towards the surface normal. In the case of the FromHeight.dds texture the results are much better - although they aren't quite the same as when we were just grabbing the z from the texture. Even though each mip level contains unit texels the results of filtering the texture means our samples aren't unit and so we end up getting the same effect of biasing the normals a little toward the surface normal.
You can download the demo here. The controls are:
Left/Right Arrow - toggle normal map texture
Up/Down Arrow - cycle through the different techniques
P - pause the spinning cubes