Creating the reflections from the different normal maps
The combination of the transparency adjusted gray scale fake normal maps and the true normal maps creates the reflection effects that are shown in the Ice Cave demo.
The transparency adjusted gray scale fake normal maps,
bumpFake, and the true normal maps,
bumpNorm, are combined proportionally. The combination
uses the following function:
half4 bumpNormalFake = lerp(bumpNorm, bumpFake, amountFakeNormalMap);
This code means that in the darker parts of the cave, the main reflection contribution comes from the gray scale fake normals. In the snowy parts of the cave, the effect comes from the object space normals.
To apply the effect using the gray scale fake normal maps, the gray scale must be converted into normal vectors. To start this process, the three components of the normal vectors are set equal to the gray scale value. In the Ice Cave demo, this means that the components vectors are between (0.3, 0.3, 0.3) and (0.8, 0.8, 0.8). Because all the components are set so that they are the same, all the normal vectors point in the same direction.
The shader applies a transformation to normal components. It uses the transform that is usually used to transform values in the range 0-1 to the range -1 to 1. The equation which performs this change is, result = 2 * value - 1. This equation changes the normal vectors so that they either point in the direction they pointed before, or the opposite direction. For example, if the original has the components (0.3, 0.3, 0.3), then the resulting normal is (-0.4, -0.4, -0.4). If the original has the components (0.8, 0.8, 0.8), then the resulting normal is (0.6, 0.6, 0.6).
After the transformation to the range -1 to 1, the vectors are fed to
reflect() function. This function is designed to
work using normalized normal vectors, however in this case the non-normalized normal is
passed to the function. The following code shows how the shader built-in function
R = reflect(I, N) = I - 2 * dot(I, N) * N
Using this function with a non-normalized input normal with a length less than one, causes the reflection vector to deviate more than expected from the normal, according to the reflection law.
When the value of the components of the normal vector goes below 0.5, the reflection vector switches to the opposite direction. When this happens, a different part of the cubemap is read. This switching between different parts of the cubemap creates the effect of uneven spots that reflect the white parts of the cubemap next to reflections of the rocky parts of the cubemap. Because the areas in the gray scale fake normal maps that cause the switches between positive and negative normals are also the areas that produce the most distorted angles on the reflected vectors, this creates an appealing swirl effect. The following figure shows this effect:
Figure 5-75 Swirl effect in the ice reflection
If the shader is programmed to use the fake normal values without the non-normalized clamped stage, then the result features diagonal bands. This is a significant difference and shows that these stages are important. The following figure shows the resulting effect without the clamp stage:
Figure 5-76 Ice reflection without the clamp stage