Search Unity

[ShaderLab] How are SubShaders selected?

Discussion in 'Shaders' started by noio, Jan 28, 2015.

  1. noio

    noio

    Joined:
    Dec 17, 2013
    Posts:
    230
    For a 2D game I would like to have sprites that write to a depth texture that I can use for post-processed FX.

    My sprite shader is an alpha blended shader. In order for anything to be written to the Depth Texture, I discovered that a number of conditions apply:
    • I need an extra SubShader in the AlphaTest queue, with LightMode = ShadowCaster set.
    • The main (sprite) SubShader also needs to be in the AlphaTest queue.
    However, the draw order is completely wrong if the main SubShader is in the AlphaTest queue. I found the above conditions through trial and error, but I would really like to gain a better understanding of this process.
    • How are SubShaders selected?
    • Why do I need "ShadowCaster" for writing to a DepthTexture?
    • Why does the Queue of the main SubShader affect drawing to the DepthTexture?
    My entire shader is pasted below. Any other remarks are welcome too; I feel there is too much trial/error going on in there.

    Code (CSharp):
    1. Shader "Custom/PowerSprite"
    2. {
    3. Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         [MaterialToggle] Recolor ("Recolor", Float) = 0
    7.         _RecolorA ("Recolor A", Color) = (0,1,0,1)
    8.         _RecolorB ("Recolor B", Color) = (0,0,1,1)      
    9.         AmbientResponse ("Ambient Response", Range (0.0, 1)) = 1
    10.     }
    11.  
    12.     // The regular, alpha blended sprite shader,
    13.     SubShader
    14.     {
    15.    
    16.         Tags
    17.         {
    18.             "Queue"="Transparent"
    19.             // Why "AlphaTest" for anything to be written to the depth texture?
    20. //            "Queue"="AlphaTest"
    21.             "IgnoreProjector"="True"
    22.             "RenderType"="Transparent"
    23.             "PreviewType"="Plane"
    24.             "CanUseSpriteAtlas"="True"
    25.         }
    26.  
    27.         Cull Off
    28.         Lighting On
    29.         ZWrite On
    30.         Fog { Mode Off }
    31.         Blend One OneMinusSrcAlpha
    32.  
    33.         CGPROGRAM
    34.         #include "Assets/Materials/Kingdom.cginc"
    35.        
    36.         #pragma surface surf LambertMaxed vertex:vert exclude_path:prepass nolightmap nodirlightmap alpha
    37.         #pragma multi_compile PIXELSNAP_OFF PIXELSNAP_ON
    38.         #pragma multi_compile RECOLOR_OFF RECOLOR_ON
    39.  
    40.         sampler2D _MainTex;
    41.         fixed AmbientResponse;
    42.         fixed4 _RecolorA;
    43.         fixed4 _RecolorB;
    44.  
    45.         struct Input
    46.         {
    47.             float2 uv_MainTex;
    48.             fixed4 color;
    49.         };
    50.        
    51.         void vert (inout appdata_full v, out Input o)
    52.         {
    53.             // I inlined the "half texel offset" of UnityPixelSnap(v.vertex)
    54.             #ifdef UNITY_HALF_TEXEL_OFFSET
    55.             v.vertex.xy += float2(-0.5f, 0.5f) * v.vertex.w / (_ScreenParams.xy * 0.5f);
    56.             #endif  
    57.             v.normal = float3(0,0,-1);
    58.             UNITY_INITIALIZE_OUTPUT(Input, o);
    59.             o.color = v.color;
    60.         }
    61.  
    62.         void surf (Input IN, inout SurfaceOutput o)
    63.         {
    64.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color;
    65.             #if defined(RECOLOR_ON)
    66.             o.Albedo = lerp(_RecolorB.rgb, _RecolorA.rgb, step(0.75f, c.a)) * c.r;
    67.             o.Albedo = lerp(o.Albedo, c.rgb, step(0.875f, c.a));
    68.             o.Alpha = step(0.5f, c.a);
    69.             o.Albedo *= o.Alpha;
    70.             #else
    71.             o.Albedo = c.rgb; // * c.a;
    72.             o.Alpha = c.a;
    73.             #endif
    74.             o.Albedo *= AmbientResponse;
    75.             o.Emission = ( 1 - AmbientResponse ) * c.rgb * c.a;
    76.         }
    77.        
    78.         ENDCG
    79.     }
    80.    
    81.    
    82.     // This is the subshader that should render into the Depth Texture
    83.     SubShader
    84.     {
    85.         Tags
    86.         {
    87.             "Queue"="AlphaTest"
    88.             "LightMode"="ShadowCaster"
    89.             "RenderType"="TransparentCutout"
    90.         }
    91.         ZWrite On
    92.         AlphaTest greater 0
    93.         Lighting Off
    94.         Fog { Mode Off }
    95.        
    96.         Pass
    97.         {
    98.             CGPROGRAM
    99.             #pragma vertex vert
    100.             #pragma fragment frag
    101.                              
    102.             uniform sampler2D _MainTex;
    103.        
    104.             struct vert_input {
    105.                 float4 vertex : SV_POSITION;
    106.                 float4 texcoord : TEXCOORD0;
    107.             };
    108.            
    109.             struct v2f {
    110.                 float4 pos : SV_POSITION;
    111.                 float2 uv : TEXCOORD0;
    112.             };
    113.  
    114.             v2f vert(vert_input v) {
    115.                   // Standard transform
    116.                   v2f o;
    117.                   o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    118.                   o.uv = v.texcoord.xy;
    119.                   return o;
    120.             }
    121.  
    122.             half4 frag(v2f i ) : COLOR {
    123.                   return tex2D( _MainTex, i.uv );
    124.             }
    125.              ENDCG
    126.         }
    127.     }
    128.    
    129.     Fallback Off
    130. }
     
  2. noio

    noio

    Joined:
    Dec 17, 2013
    Posts:
    230
    So the Unity 5 release notes mention this:
    But I don't know quite what to make of this. What—for example—is a "ShadowCaster pass type". I assume they're talking about "LightMode"="ShadowCaster"? Then what is this "LightType" thing on the previous line?
     
    Last edited: Feb 2, 2015