I am trying to understand what Unity does when it imports a normal map.
As per unity docs - in order to make a normal map I need a gray scale image (Not sure that being 8 bit is mandatory). When importing the texture as a normal map created from grey scale, Unity constructs a normal map which as far as I can see is actually a 4 channel image - each channel being 8 bits.
Here is the first question - could any one direct me to what is actually done in this conversion - how are the x,y and z components of the normal calculated from a single 8 bit channel grey scale?
Now looking into the UnityCG.cginc file - unpacking normals uses this code:
inline fixed3 UnpackNormalDXT5nm (fixed4 packednormal)
{
fixed3 normal;
normal.xy = packednormal.wy * 2 - 1;
#if defined(SHADER_API_FLASH)
// Flash does not have efficient saturate(), and dot() seems to require an extra register.
normal.z = sqrt(1 - normal.x*normal.x - normal.y * normal.y);
#else
normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));
#endif
return normal;
}
inline fixed3 UnpackNormal(fixed4 packednormal)
{
#if (defined(SHADER_API_GLES) || defined(SHADER_API_GLES3)) && defined(SHADER_API_MOBILE)
return packednormal.xyz * 2 - 1;
#else
return UnpackNormalDXT5nm(packednormal);
#endif
}
So here we can clearly see that for mobile unity just uses the xyz components for calculating the normal, but for desktop/flash the X component of the normal is taken from the w/alpha of the normal texture, the Y component from the y and the Z component in actually calculated from the previous two.
So here is the second question - would I be correct assuming that the X component of the normal is copied into the w/alpha channel of the normal map texture during it’s creation?
My third question - As you can also import any texture as a normal map (without creating it from a grey scale) - can I assume that for mobile platforms I just need a 3 channel texture from which the normal will be extracted, while for desktop and/flash I would need a 4 channel textures with the x component of the normal copied into the alpha channel?
Fourth question:
Would it be correct to assume that for desktops/flash the 4th channel is no longer available for usage for things such as height maps while for mobile platform I could use the 4th channel for extra info?
This seems like a convoluted implementation by Unity for storing/calculating normals. What do you think about the notion of creating cginc with a custom consistent implementation for extracting normals? For this to happen though I really need to understand how the normal components are calculated before they are packed into the texture channels.