I’ve been working into the shader I was doing in the last blog post a little more. As I was finished with transparency and set my alpha to 1, I noticed that the light seemed off, with a band of specular light across the middle. This was because I had forgotten to unpack my normal!
When a map is marked as a normal map in Unity (and many other game engines), it changes its GPU compression type to DXT5. DXT or BC 5 compression ditches the blue channel in order to reduce file size. This works well with normal maps as the blue channel in a normal map represents the Z component of the surface normal and the Z should always be facing in the opposite direction from the camera. As we need the blue channel in order to calculate our normals, we use the UnpackNormal function.
fixed4 n = tex2D(_Normal, IN.uv_Normal); o.Normal = UnpackNormal(n); //unpacks from dxt5nm to rgb
Below is a comparison of an unpacked normal vs a dxt5 packed normal – in the packed version the Z is always set to 0, regardless of the result of the dot product with the camera heading.