Search Unity

When disabling a point light in Unity, unity_LightColor not zeroing out.

Discussion in 'Shaders' started by cjddmut, Nov 24, 2013.

  1. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    120
    I'm currently learning how to write shaders and the exercise I've given myself is to recreate the built in Unity shaders writing the vertex/fragment shaders. I'm at the point where I'm calculating light from the four point lights in the forward base phase and I noticed an odd behavior. If I only have one active light in the scene (which is a point light) and I disable it then unity_LightColor[0] doesn't zero out as expected, it instead become a gray color (I'd guess close to 0.5 0.5 0.5).

    Here is a sample shader that reproduces the behavior I'm noticing.

    Code (csharp):
    1.  
    2. Shader "TestShader"
    3. {
    4.     SubShader
    5.     {  
    6.         Pass
    7.         {  
    8.             Tags {"LightMode" = "ForwardBase"}
    9.  
    10.             CGPROGRAM
    11.  
    12.             #pragma vertex vert
    13.             #pragma fragment frag
    14.  
    15.             // base structs
    16.             struct vertexInput
    17.             {
    18.                 float4 vertex : POSITION;
    19.             };
    20.  
    21.             struct vertexOutput
    22.             {
    23.                 float4 pos : SV_POSITION;
    24.                 float4 color : COLOR;
    25.             };
    26.  
    27.             // vertex function
    28.             vertexOutput vert(vertexInput v)
    29.             {
    30.                 vertexOutput output;
    31.  
    32.                 // Have the object by a point light, now disable that point light.
    33.                 // The object becomes grey instead of black. This is not the case for
    34.                 // lights 1 through 3, only 0.
    35.                 output.color = unity_LightColor[0];
    36.                
    37.                 output.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    38.                 return output;
    39.             }
    40.  
    41.             // fragment function
    42.             float4 frag(vertexOutput i) : COLOR
    43.             {
    44.                 return i.color;
    45.             }
    46.  
    47.         ENDCG
    48.         }
    49.     }
    50. }
    51.  
    I first noticed this cause my shader had lighting applied even when I disabled the point light. The built in unity shader does not appear to have this problem. So is there a way to key off if it is junk values and to not calculate lighting? Right now I rely on the color being black so it won't impact the object.

    Thanks!
     
  2. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    There are defines to do with vertex lights, you'll need to use then to skip the code if there are no vertex lights. Check the built in surface shaders using #pragma debug for usage.
     
  3. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    120
    I found them and it fixed it, thanks!

    For anyone else who might hit this issue the solution is to wrap the vertex light calculation code inside the following ifdef.
    Code (csharp):
    1.  
    2. // It appears that you need this pragma declared in the pass for this to work.
    3. #pragma multi_compile_fwdbase
    4.  
    5. ...
    6.  
    7. #ifdef VERTEXLIGHT_ON
    8. // Calculate lights
    9. #endif
    10.  
     
    gz7190 likes this.
unityunity