Self-Shadowed Bump maps
Sunday, February 7, 2010 at 12:17AM
Post a Comment For those who don't know, Self-Shadowed Bump maps were originally developed by Valve for use with their Radiosity Normal Mapping technology. After I decided to make the switch to a renderer built around pre-computed data, this was one of the first things I decided to try out. If you wish to read more about the technique, the following links have provided me with most of my information on the subject.
Links:
Efficient Self-Shadowed Radiosity Normal Mapping
Surface Detail Maps with Soft Self-Shadowing
Shading in Valve's Source Engine
SSBump Generator (used to make the maps)
Overview:
During the course of my experiments, I have verified all the benefits that Valve described in their papers. However, I have also discovered a few drawbacks that they didn't mention. Keeping that in mind, I have pooled and summarized my findings from all the papers and my own experiments.
Benefits:
-
Directional Occlusion
-
Correct filtering
-
Detail mapping
-
Recovers bent normals
-
Better use of byte precision
-
Faster than tangent-space normal maps
-
NOTE: Only for RNM, not for general diffuse lighting
-
Drawbacks:
-
Diffuse Lighting expense
-
In order to get diffuse lighting with directional occlusion, each light direction has to be projected onto the basis. This boils down to the same amount of math as a 3x3 matrix multiply, per light direction.
-
-
Poor compression
-
DXTC causes artifacts at detail edges, and nasty blocky artifacts in specular/reflection
-
RGB5 is acceptable for diffuse lighting, but produces banding for specular/reflections. Also, this format is not supported by Direct3D 10.
-
Visuals:
Figure 1. 1, Height map; 2, Normal map; 3, RNM map; 4, SS Bump map, 5, no DO; 6, DO; 7, reflection
Figure 2. 1, Detail map; 2, combined with SS Bump; 3, diffuse lighting
Figure 3. 1, DXT1 SS Bump map; 2, diffuse lighting; 3, reflection
Figure 4. 1, RGB5 diffuse lighting; 2, reflection
Usage Tips:
Most tools that generate SS Bump maps will format them for the Source Engine, so they assume that the Y axis is inverted. This will cause issues with any programs that use a right-handed coordinate system. Fortunately, this issue can easily be fixed in a decent image editing program (Photoshop, Gimp, etc).
Tangent-Space normals:
Here, you just need to invert the contents of the green channel to invert the Y-axis.
Figure 5. 1, normal LH; 2, normal RH
Self-Shadowed Bump maps:
Here, you have to swap the contents of the green and blue channels.
Figure 6. 1, SS Bump LH; 2, SS Bump RH
Other than that, I thought I'd mention a problem I encountered while writing shader code to use these maps. The order of the bump basis vectors as Valve listed them in the paper can be a bit confusing, and will produce incorrect results that will have you scratching your head for days. To save you that trouble, here is how they should appear:
Code:
static half3 bumpBasis[3] =
{
half3(sqrt(2.0) / sqrt(3.0), 0.0, 1.0 / sqrt(3.0)),
half3( -1.0 / sqrt(6.0), 1.0 / sqrt(2.0), 1.0 / sqrt(3.0)),
half3( -1.0 / sqrt(6.0), -1.0 / sqrt(2.0), 1.0 / sqrt(3.0))
};
Final Thoughts:
Despite the added storage and lighting cost, the benefits from using this technique are too enticing for me to pass up. So I have decided to integrate this technology into my new renderer for handling static objects. Dynamic objects, or anything that needs detail normal mapping, will still use Partial Derivative Normal maps for efficiency & flexibility. Between these two solutions, I should have a sufficiently versatile system for generating pleasing visuals.































