Ok, I hope this isn’t a double post, because my last one seemed to disappear into the ether.
I am writing a shader that uses 4 pairs of diffuse/normal maps. In an effort to reuse UV coordinates and reduce the number of TEXCOORD interpolators in my shader, I have each normal map use the same UV as its paired diffuse map. For example:
struct Input
{
float2 uv_MainTex;
float2 uv_Diffuse2;
float2 uv_Diffuse3;
float2 uv_Diffuse4;
};
…
half4 tex2 = tex2D(_Diffuse2, IN.uv_Diffuse2);
half4 normal2 = UnpackNormal(tex2D(_Normal2, IN.uv_Diffuse2));
This trick works fine in forward rendering, but breaks under deferred rendering. I think I know why. When the deferred renderer creates a shader pass for the “Normal/Depth” pass, it tries to optimize by throwing out unused stuff. It (erroneously, in my case) assumes that because the _Diffuse2 texture is unused, then the IN.uv_Diffuse2 UV is also not needed. The result is that (under deferred) my diffuse textures all tile as expected, but the normal maps do not.
To test my theory, I reversed it so the diffuse textures used the normal map UVs. As expected, the diffuse textures no longer tiled, but the normal maps did.
Ideally, the compiler would recognize which UV interpolators are actually used, rather than (apparently) discarding them based on some naming convention.
Until then, are there any work-arounds for this? One possibility might be a #define that indicates which pass is currently being compiled. I could then modify my code to do something like this:
struct Input
{
#ifdef MATERIAL_PASS
float2 uv_MainTex;
float2 uv_Diffuse2;
float2 uv_Diffuse3;
float2 uv_Diffuse4;
#endif
#ifdef NORMAL_DEPTH_PASS
float2 uv_NormalMap;
float2 uv_Normal2;
float2 uv_Normal3;
float2 uv_Normal4;
#endif
};
…
#ifdef MATERIAL_PASS
half4 tex2 = tex2D(_Diffuse2, IN.uv_Diffuse2);
half4 normal2 = UnpackNormal(tex2D(_Normal2, IN.uv_Diffuse2));
#endif
#ifdef NORMAL_DEPTH_PASS
half4 tex2 = tex2D(_Diffuse2, IN.uv_Normal2);
half4 normal2 = UnpackNormal(tex2D(_Normal2, IN.uv_Normal2));
#endif
Thoughts?