Search Unity

Shader doesn't execute second pass

Discussion in 'Shaders' started by thielmlw, Oct 7, 2021.

  1. thielmlw

    thielmlw

    Joined:
    Sep 9, 2021
    Posts:
    5
    Hello, I am trying to make a shader that makes a silhouette of an object visible when the object is occluded by something based off of answers in this thread. I'm running into an issue however where only the first pass of the shader gets executed and the second one is seemingly ignored. If I switch the order around, whichever the first one is is the one that works. I cannot for the life of me figure out what could cause this, no errors are thrown or anything. The only remotely relevant google result is someone who had an extra bracket and ignored the error telling them they had an extra bracket. This has really been driving me nuts so I appreciate any help offered.


    Code for reference:
    Code (CSharp):
    1. Shader "Unlit/Universal outline shader v2"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.         _OutlineColor("Outline Color", Color) = (0,0,0,0)
    7.         _ScaleFactor("Scale Factor", Range(0.0, 2.0)) = 0.01
    8.     }
    9.     SubShader
    10.     {
    11.         Tags { "RenderType"="Opaque" "Queue"="Geometry+1" }
    12.  
    13.         //silhouette pass
    14.         Pass
    15.         {
    16.             Name "Silhouette"
    17.  
    18.             ZTest Greater
    19.             ZWrite Off
    20.  
    21.             CGPROGRAM
    22.             #pragma vertex vert
    23.             #pragma fragment frag
    24.  
    25.             #include "UnityCG.cginc"
    26.  
    27.             struct appdata
    28.             {
    29.                 float4 vertex : POSITION;
    30.                 float2 uv : TEXCOORD0;
    31.             };
    32.  
    33.             struct v2f
    34.             {
    35.                 float2 uv : TEXCOORD0;
    36.                 float4 vertex : SV_POSITION;
    37.             };
    38.  
    39.             sampler2D _MainTex;
    40.             float4 _MainTex_ST;
    41.             float4 _OutlineColor;
    42.  
    43.             v2f vert(appdata v)
    44.             {
    45.                 v2f o;
    46.                 o.vertex = UnityObjectToClipPos(v.vertex);
    47.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    48.                 return o;
    49.             }
    50.  
    51.             fixed4 frag(v2f i) : SV_Target
    52.             {
    53.                 // sample the texture
    54.                 fixed4 col = tex2D(_MainTex, i.uv);
    55.                 return _OutlineColor;
    56.             }
    57.             ENDCG
    58.         }
    59.  
    60.         //regular pass
    61.         Pass
    62.         {
    63.             Name "StandardUnlit"
    64.             Tags {"Queue"="Geometry+2"}
    65.  
    66.             ZTest LEqual
    67.             ZWrite On
    68.  
    69.             CGPROGRAM
    70.             #pragma vertex vert
    71.             #pragma fragment frag
    72.  
    73.             #include "UnityCG.cginc"
    74.  
    75.             struct appdata
    76.             {
    77.                 float4 vertex : POSITION;
    78.                 float2 uv : TEXCOORD0;
    79.             };
    80.  
    81.             struct v2f
    82.             {
    83.                 float2 uv : TEXCOORD0;
    84.                 float4 vertex : SV_POSITION;
    85.             };
    86.  
    87.             sampler2D _MainTex;
    88.             float4 _MainTex_ST;
    89.  
    90.             v2f vert (appdata v)
    91.             {
    92.                 v2f o;
    93.                 o.vertex = UnityObjectToClipPos(v.vertex);
    94.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    95.                 return o;
    96.             }
    97.  
    98.             fixed4 frag (v2f i) : SV_Target
    99.             {
    100.                 // sample the texture
    101.                 fixed4 col = tex2D(_MainTex, i.uv);
    102.                 return col;
    103.             }
    104.             ENDCG
    105.         }
    106.     }
    107. }
    108.  
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    URP doesn't automatically run all shader passes for performance reasons.

    You could make a second material that has the other pass enabled and add it to the object's material list. It would effectively be the same.
     
    Niter88 likes this.
  3. thielmlw

    thielmlw

    Joined:
    Sep 9, 2021
    Posts:
    5
    I had been doing that, but as I understand it I need to have this be one shader so I can be certain that the silhouette is drawn before the object in order to prevent the silhouette being visible through the object itself. Also Unity yells at me for doing that and says that it costs performance. Is there no way to force it to run every pass?
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    You just need to set the Render Queue on the Silhouette material to be lower than the queue value on the other one.

    That warning is why it doesn't run every pass any more, because multiple passes were a hidden cost many weren't aware of. You can ignore this warning since you are aware now that rendering the object multiple times (shader passes), is more costly.

    The other option is to manually render the passes from code. But it's simpler to just have 2 materials.
     
  5. thielmlw

    thielmlw

    Joined:
    Sep 9, 2021
    Posts:
    5
    OK, I will try that, thank you very much.
     
  6. Niter88

    Niter88

    Joined:
    Jul 24, 2019
    Posts:
    112
    Hello @Invertex
    do you know how to bypass that and execute the second pass?
    I've even written a question in StackOverflow
    I am using this on mobile so I prefer to use one material with two passes if possible
     
  7. Niter88

    Niter88

    Joined:
    Jul 24, 2019
    Posts:
    112
    Just updating, I found two solutions and posted 'em in depth in that StackOverflow thread. I was able to bypass the passes to my needs
     
    RaventurnPatrick likes this.