The WorldSpaceNormalCreator shader
The shader code that implements the conversion is quite straightforward. Instead of using the actual vertex position, it uses the texture coordinate of the vertex as its position. This causes the object to be projected onto a 2D plane, the same as when texturing.
To make the OpenGL pipeline work correctly, the UV coordinates are moved
from the standard [0,1]
range to the [-1,1]
range and invert the Y coordinate. The Z coordinate
is not used so it can be set to 0
or any value within
the near and far clip planes:
output.pos = half4(input.tex.x*2.0 - 1.0,((1.0-input.tex.y)*2.0 - 1.0), 0.0, 1.0); output.tc = input.tex;
The normal, tangent and bitangent are computed in the vertex shader and passed to the fragment shader to execute the conversion:
output.normalInWorld = normalize(mul(half4(input.normal, 0.0), _World2Object).xyz); output.tangentWorld = normalize(mul(_Object2World, half4(input.tangent.xyz, 0.0)).xyz); output.bitangentWorld = normalize(cross(output.normalInWorld, output.tangentWorld) * input.tangent.w);
The fragment shader:
- Converts the normal from tangent space to world space.
- Scales the normal to the
[0,1]
range. - Outputs the normal to the new texture.
The following code shows this:
half3 normalInWorld = half3(0.0,0.0,0.0); half3 bumpNormal = UnpackNormal(tex2D(_BumpMapGlobal, input.tc)); half3x3 local2WorldTranspose = half3x3( input.tangentWorld, input.bitangentWorld, input.normalInWorld); normalInWorld = normalize(mul(bumpNormal, local2WorldTranspose)); normalInWorld = normalInWorld*0.5 + 0.5; return half4(normalInWorld,1.0);
The following image shows a tangent space normal map before processing:
Figure 5-90 Original tangent space normal map

The following image shows a world space normal map generated by the tool:
Figure 5-91 Generated world space normal map
