Conditional Shader Variant USING_DIRECTIONAL_LIGHT

Hi,

I’m in trouble trying to multicompile a shader variant which is active only when a directional light is active in the scene.
Accordingly to UnityCG.cginc this should be possible, in fact WorldSpaceLightDir is defined this way:

// Computes world space light direction
inline float3 WorldSpaceLightDir( in float4 v )
{
    float3 worldPos = mul(_Object2World, v).xyz;
    #ifndef USING_LIGHT_MULTI_COMPILE
        return _WorldSpaceLightPos0.xyz - worldPos * _WorldSpaceLightPos0.w;
    #else
        #ifndef USING_DIRECTIONAL_LIGHT
        return _WorldSpaceLightPos0.xyz - worldPos;
        #else
        return _WorldSpaceLightPos0.xyz;
        #endif
    #endif
}

Now I’ve created a small shader trying that display a color accordingly to the defined variant:

Shader "Test"  {
   SubShader {
      Pass {  
         //Tags { "LightMode" = "ForwardBase"  }
     
         CGPROGRAM
 
         #pragma vertex vert
         #pragma fragment frag
         // #pragma multi_compile_fwdbase
        //      #pragma multi_compile_fwdadd
        #pragma multi_compile_lightpass
    
        #include "UnityCG.cginc"
      
         struct vertexInput {
            float4 vertex : POSITION;
            half3 normal : NORMAL;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
         };
         vertexOutput vert(vertexInput v)
         {
            vertexOutput output;
            output.pos = mul(UNITY_MATRIX_MVP, v.vertex);
            return output;
         }
         fixed4 frag(vertexOutput input) : COLOR
         {
            #ifndef USING_LIGHT_MULTI_COMPILE
                return float4(1,0,0,1);
            #else
                #ifndef USING_DIRECTIONAL_LIGHT
                    return float4(0,1,0,1);
                #else
                     return float4(0,0,1,1);
                #endif
            #endif

         }
         ENDCG
      }
   }
   // The definition of a fallback shader should be commented out
   // during development:
}

#pragma multi_compile_lightpass should guarantee that multi compilation of variants is enabled for different light types.(I tried also all the combination I know such as multi_compile_fwd[base|add]).

If #pragma multi_compile_lightpass isn’t defined then the fragment display red color as expected(not defined USING_LIGHT_MULTI_COMPILE).

If it is defined the displayed color is always blu, no matter if a directional light is present and active in the scene( USING_DIRECTIONAL_LIGHT appears not defined ).

I’m using Unity version 4.5.3 (but I don’t think it’s a bug…just I’m doing something wrong).
What am I doing wrong?

Well, your lightmode is forwardbase. Which according to the pass tags page handles:

So, it seems the only realtime light handled in this mode is the main directional light. Why not try to remove the lightmode tag?

Ok…good point, but I already considered that:

  • Even removing the tag doesn’t fix the issue
  • Despite the main directional light is only available in forward base pass, it might not (and this is one specific case I want to handle). In fact forward base pass is executed even if no directional lights are present in the scene.

Maybe, accordingly to your suggestion, USING_DIRECTIONAL_LIGHT is always defined in forward base… It would be at least inconsistent with point lights ans spot lights similar defines, which instead are selectively activated in forward add pass depending on the type (I have to check this, it’s a lot of time I don’t use those macro)

To avoid having another shader switch, I can imagine the directional light is always defined in forward base. It’s not a very difficult calculation, so the intensity can be set to 0 if it’s not actually there.