Search Unity

Question Shader AlphaTest Cutout VariableName has to be "Cutoff"?

Discussion in 'Shaders' started by ccoddes, Apr 6, 2021.

  1. ccoddes

    ccoddes

    Joined:
    Mar 6, 2017
    Posts:
    3
    Hello,

    I'm relatively new to working with Unity shaders. I was doing a course on Shaders and was experimenting with the Surface Shader when I noticed a weird behavior with the
    alphatest:VariableName
    parameter. It seems like if there also exists a
    alpha:fade
    parameter, the
    VariableName
    here HAS to be
    _Cutoff
    for alpha cutout to work.

    To illustrate what I mean, this is a simple Quad which has the Material containing my Shader (the leaves). It has Transparency for the main texture, that also does not cast shadows on the areas which are transparent due to the alpha cutoff.

    The correct result is that the leaves texture has some transparency, and the shadow produced follows the shape of the leaves:
    unity-correct-transparency.PNG

    The Shader:
    Code (CSharp):
    1. Shader "Custom/Leaves"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Texture", 2D) = "white" {}
    6.         _Color ("Main Color", Color) = (1, 1, 1, 1)
    7.         _Cutoff("Alpha Cutoff", Range(0, 1)) = 0.5
    8.     }
    9.     SubShader
    10.     {
    11.         Tags { "Queue" = "Transparent" }
    12.  
    13.         CGPROGRAM
    14.         #pragma surface surf Lambert alphatest:_Cutoff alpha:fade addshadow //<-- Variable Name has to be "Cutoff" for alphatest to work?
    15.  
    16.         sampler2D _MainTex;
    17.         fixed4 _Color;
    18.  
    19.         struct Input
    20.         {
    21.             float2 uv_MainTex;
    22.         };
    23.  
    24.         void surf (Input IN, inout SurfaceOutput o)
    25.         {
    26.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    27.             o.Albedo = c.rgb;
    28.             o.Alpha = c.a;
    29.         }
    30.         ENDCG
    31.     }
    32.     FallBack "Transparent/Cutout/VertexLit"
    33. }
    34.  
    HOWEVER, thinking that the
    alphatest
    can use another VariableName instead of "Cutoff", I tried changing the Variable Name to "CutoffCustom", and suddenly the alpha cutoff no longer happens. (Changes are commented)

    Code (CSharp):
    1. Shader "Custom/Leaves"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Texture", 2D) = "white" {}
    6.         _Color ("Main Color", Color) = (1, 1, 1, 1)
    7.         _CutoffCustom("Alpha Cutoff", Range(0, 1)) = 0.5  //<-- Changed name to "CutoffCustom"
    8.     }
    9.     SubShader
    10.     {
    11.         Tags { "Queue" = "Transparent" }
    12.  
    13.         CGPROGRAM
    14.         #pragma surface surf Lambert alphatest:_CutoffCustom alpha:fade addshadow //<-- Variable Name has to be "Cutoff" for alphatest to work?
    15.  
    16.         sampler2D _MainTex;
    17.         fixed4 _Color;
    18.         float _CutoffCustom; //<-- Added
    19.  
    20.         struct Input
    21.         {
    22.             float2 uv_MainTex;
    23.         };
    24.  
    25.         void surf (Input IN, inout SurfaceOutput o)
    26.         {
    27.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    28.             o.Albedo = c.rgb;
    29.             o.Alpha = c.a;
    30.         }
    31.         ENDCG
    32.     }
    33.     FallBack "Transparent/Cutout/VertexLit"
    34. }
    35.  
    The result is that the the shadow now does not ignore the areas with transparency, resulting in a "block" shadow:

    unity-wrong-transparency.PNG

    I'm really confused with this behavior. Why does the VariableName have to be exactly "_Cutoff" when used by the alphatest?

    Most amazingly, the custom VariableName actually works if there is no
    alpha:fade
    parameter (although I do want the texture to have some alpha fade eventually)

    Code (CSharp):
    1. Shader "Custom/Leaves"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Texture", 2D) = "white" {}
    6.         _Color ("Main Color", Color) = (1, 1, 1, 1)
    7.         _CutoffCustom("Alpha Cutoff", Range(0, 1)) = 0.5  //<-- Changed name to "CutoffCustom"
    8.     }
    9.     SubShader
    10.     {
    11.         Tags { "Queue" = "Transparent" }
    12.  
    13.         CGPROGRAM
    14.         #pragma surface surf Lambert alphatest:_CutoffCustom addshadow //<-- This works if there is no "alpha:fade"
    15.  
    16.         sampler2D _MainTex;
    17.         fixed4 _Color;
    18.  
    19.         struct Input
    20.         {
    21.             float2 uv_MainTex;
    22.         };
    23.  
    24.         void surf (Input IN, inout SurfaceOutput o)
    25.         {
    26.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    27.             o.Albedo = c.rgb;
    28.             o.Alpha = c.a;
    29.         }
    30.         ENDCG
    31.     }
    32.     FallBack "Transparent/Cutout/VertexLit"
    33. }
    34.  
    I'm trying to understand what is going on here. Why does the VariableName have to be "Cutoff" specifially, and why is it only in the case where there is no alpha:fade parameter? If anyone has any explanation it would help greatly as I have been trying to figure it out for a long while now.
     
    Last edited: Apr 7, 2021
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,336
    It appears you've found a bug or undocumented "feature" of Surface Shaders. The short version is when using
    alpha:fade
    the
    addshadow
    is completely ignored and your shader is instead using the shadow caster from the fallback. Since the "Transparent/Cutout/VertexLit" shader uses
    _Cutoff
    , it works when you use the same name for your property.
     
    ccoddes likes this.
  3. ccoddes

    ccoddes

    Joined:
    Mar 6, 2017
    Posts:
    3
    Thanks @bgolus. Is the reason for
    alpha:fade
    being incompatible with the
    addshadow
    parameter a general shader concept, or unexpected behavior in Unity shader's case? (I'm really new to shaders so am trying to understand the concepts)

    Otherwise, that makes sense. I hope you don't mind me asking (for the sake of learning), what was the method you used to identify that it was using the Fallback shader's shadow caster, and how did you see that the fallback shader uses the
    _Cutoff
    property?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,336
    I have no idea why it doesn't work. It's probably a bug. And one I wouldn't expect Unity to fix unfortunately.