Search Unity

Conditional Shader Variant USING_DIRECTIONAL_LIGHT

Discussion in 'Shaders' started by Heisenbug, Feb 18, 2015.

  1. Heisenbug

    Heisenbug

    Joined:
    Aug 31, 2012
    Posts:
    40
    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:

    Code (CSharp):
    1. // Computes world space light direction
    2. inline float3 WorldSpaceLightDir( in float4 v )
    3. {
    4.     float3 worldPos = mul(_Object2World, v).xyz;
    5.     #ifndef USING_LIGHT_MULTI_COMPILE
    6.         return _WorldSpaceLightPos0.xyz - worldPos * _WorldSpaceLightPos0.w;
    7.     #else
    8.         #ifndef USING_DIRECTIONAL_LIGHT
    9.         return _WorldSpaceLightPos0.xyz - worldPos;
    10.         #else
    11.         return _WorldSpaceLightPos0.xyz;
    12.         #endif
    13.     #endif
    14. }
    15.  
    Now I've created a small shader trying that display a color accordingly to the defined variant:

    Code (CSharp):
    1. Shader "Test"  {
    2.    SubShader {
    3.       Pass {  
    4.          //Tags { "LightMode" = "ForwardBase"  }
    5.      
    6.          CGPROGRAM
    7.  
    8.          #pragma vertex vert
    9.          #pragma fragment frag
    10.          // #pragma multi_compile_fwdbase
    11.         //      #pragma multi_compile_fwdadd
    12.         #pragma multi_compile_lightpass
    13.    
    14.         #include "UnityCG.cginc"
    15.      
    16.          struct vertexInput {
    17.             float4 vertex : POSITION;
    18.             half3 normal : NORMAL;
    19.          };
    20.          struct vertexOutput {
    21.             float4 pos : SV_POSITION;
    22.          };
    23.          vertexOutput vert(vertexInput v)
    24.          {
    25.             vertexOutput output;
    26.             output.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    27.             return output;
    28.          }
    29.          fixed4 frag(vertexOutput input) : COLOR
    30.          {
    31.             #ifndef USING_LIGHT_MULTI_COMPILE
    32.                 return float4(1,0,0,1);
    33.             #else
    34.                 #ifndef USING_DIRECTIONAL_LIGHT
    35.                     return float4(0,1,0,1);
    36.                 #else
    37.                      return float4(0,0,1,1);
    38.                 #endif
    39.             #endif
    40.  
    41.          }
    42.          ENDCG
    43.       }
    44.    }
    45.    // The definition of a fallback shader should be commented out
    46.    // during development:
    47. }
    #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?
     
    Last edited: Feb 18, 2015
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    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?
     
  3. Heisenbug

    Heisenbug

    Joined:
    Aug 31, 2012
    Posts:
    40
    Ok..good point, but I already considered that:

    1. Even removing the tag doesn't fix the issue
    2. 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)
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    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.