Search Unity

  1. Get the latest news, tutorials and offers directly to your inbox with our newsletters. Sign up now.
    Dismiss Notice

SHADERPASS_SHADOWCASTER and testing for the shadowcaster pass

Discussion in 'Universal Render Pipeline' started by ElliotB, Jan 5, 2021.

  1. ElliotB

    ElliotB

    Joined:
    Aug 11, 2013
    Posts:
    27
    Hi,

    In URP 8.2.x, I used SHADERPASS_SHADOWCASTER to change the behavior of some custom nodes in shadergraph during shadowcasting passes:
    Code (csharp):
    1. #ifdef SHADERPASS_SHADOWCASTER
    2. // do something while shadowcasting...
    3. #else
    4. // do something normally...
    5. #endif
    6.  
    I've upgraded to 2020.2 and URP 10.2.2 and this no longer works. I can't seem to find any reference in the changelog or docs about this functionality. I did see on the (now retired) git that some references were made to 'Fix SHADERPASS inconsistency between pipelines', see eg https://github.com/Unity-Technologies/Graphics/commit/db4dddf00233cbe55aa78414d6985ce292a70b46

    This looks like changes were made to the format:
    Code (csharp):
    1. #if (SHADERPASS == SHADERPASS_SHADOWCASTER)
    2. // stuff
    3. #endif
    4.  
    However, I can't seem to get this to work in my shader! Whatever I try the value is always true. What is the 'correct' way to test for the shadowcasting pass in URP 10?

    Cheers,
    Elliot
     
  2. ElliotB

    ElliotB

    Joined:
    Aug 11, 2013
    Posts:
    27
    More information:

    I've looked at the ShaderLab code generated by ShaderGraph for each version.

    In the URP 8.2 version, the shadowcaster pass looks like the following:
    Code (csharp):
    1.  
    2.         Pass
    3.         {
    4.             Name "ShadowCaster"
    5.             Tags
    6.             {
    7.                 "LightMode" = "ShadowCaster"
    8.             }
    9.  
    10.             // Render State
    11.             Blend One Zero, One Zero
    12.             Cull Off
    13.             ZTest LEqual
    14.             ZWrite On
    15.             // ColorMask: <None>
    16.  
    17.             HLSLPROGRAM
    18.             #pragma vertex vert
    19.             #pragma fragment frag
    20.        
    21.             // Debug
    22.             // <None>
    23.        
    24.             // --------------------------------------------------
    25.             // Pass
    26.        
    27.             // Pragmas
    28.             #pragma prefer_hlslcc gles
    29.             #pragma exclude_renderers d3d11_9x
    30.             #pragma target 2.0
    31.             #pragma multi_compile_instancing
    32.  
    33.  ....(a whole forest of keyword permutations, followed by)...
    34.  
    35.             #if defined(UNITY_SUPPORT_INSTANCING) && defined(INSTANCING_ON)
    36.             #define UNITY_DOTS_INSTANCING_ENABLED
    37.             #endif
    38.             #define SHADERPASS_SHADOWCASTER
    39.             //-------------------------------------------------------------------------------------
    40.             // Dots Instancing vars
    41.             //-------------------------------------------------------------------------------------
    42. ....
    43.  
    Hence, SHADERPASS_SHADOWCASTER is clearly defined in the Shadowcasting pass.

    In URP 10.2 the generated shader is different:
    Code (csharp):
    1.  
    2.             Pass
    3.             {
    4.                 Name "ShadowCaster"
    5.                 Tags
    6.                 {
    7.                     "LightMode" = "ShadowCaster"
    8.                 }
    9.    
    10.                 // Render State
    11.                 Cull Off
    12.                 Blend One Zero
    13.                 ZTest LEqual
    14.                 ZWrite On
    15.                 ColorMask 0
    16.    
    17.                 // Debug
    18.                 // <None>
    19.    
    20.                 // --------------------------------------------------
    21.                 // Pass
    22.    
    23.                 HLSLPROGRAM
    24.    
    25.                 // Pragmas
    26.                 #pragma target 4.5
    27.                 #pragma exclude_renderers gles gles3 glcore
    28.                 #pragma multi_compile_instancing
    29.                 #pragma multi_compile _ DOTS_INSTANCING_ON
    30.                 #pragma vertex vert
    31.                 #pragma fragment frag
    32.    
    33.                 #if SHADER_TARGET >= 35 && (defined(SHADER_API_D3D11) || defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_PSSL) || defined(SHADER_API_VULKAN) || defined(SHADER_API_METAL))
    34.                     #define UNITY_SUPPORT_INSTANCING
    35.                 #endif
    36.                 #if defined(UNITY_SUPPORT_INSTANCING) && defined(INSTANCING_ON)
    37.                     #define UNITY_HYBRID_V1_INSTANCING_ENABLED
    38.                 #endif
    39.                 #if defined(UNITY_HYBRID_V1_INSTANCING_ENABLED)
    40.                 #define HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS \
    41.                 UNITY_DEFINE_INSTANCED_PROP(float, _PixelSize_Array)\
    42.                 UNITY_DEFINE_INSTANCED_PROP(float4, _PixelGridOrigin_Array)
    43.                 #define _PixelSize UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, _PixelSize_Array)
    44.                 #define _PixelGridOrigin UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, _PixelGridOrigin_Array)
    45.                 #endif
    46.    
    47.                 // Keywords
    48.                 // PassKeywords: <None>
    49.                 #pragma shader_feature_local _ COLOR_GRADING_ON
    50.                 #pragma shader_feature_local _ RECEIVE_SHADOWS_ON
    51.                 #pragma shader_feature_local _ USE_OBJECT_POSITION_ON
    52.                 #pragma shader_feature_local _ NORMAL_MAP_ON
    53.                 #pragma shader_feature_local _ USE_EMISSION_ON
    54.                 #pragma shader_feature_local _ USE_ALPHA_ON
    55.                
    56. ...(a whole forest of keyword permutations, followed by)...
    57.    
    58.                 #define FEATURES_GRAPH_VERTEX
    59.                 /* WARNING: $splice Could not find named fragment 'PassInstancing' */
    60.                 #define SHADERPASS SHADERPASS_SHADOWCASTER
    61.                 /* WARNING: $splice Could not find named fragment 'DotsInstancingVars' */
    62.    
    63.                 // Includes
    64.                 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    65.                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    66.                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    67.                 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl"
    68.                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"
    69.    ...
    So the #define SHADERPASS_SHADOWCASTER has been swapped for #define SHADERPASS SHADERPASS_SHADOWCASTER, and I would expect the if statement in the first post to now work:
    Code (csharp):
    1. #if (SHADERPASS == SHADERPASS_SHADOWCASTER)
    But it still doesn't! The SHADERPASS_SHADOWCASTER statement is defined in Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl. If I put the following into a ShaderGraph Custom Node...
    Code (csharp):
    1. #ifndef UNIVERSAL_SHADERPASS_INCLUDED
    2. #error "Universal ShaderPass not included."
    3. #endif
    ...then I receive the error 'Universal ShaderPass not included' (the same works if I test whether SHADERPASS_SHADOWCASTER is defined).

    The 10.2 generated ShadowCaster Pass hlsl ends with:
    Code (csharp):
    1.                 // --------------------------------------------------
    2.                 // Main
    3.    
    4.                 #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl"
    5.                 #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/Varyings.hlsl"
    6.                 #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShadowCasterPass.hlsl"
    7.    
    8.                 ENDHLSL
    9.             }
    10.  
    ...which does include the ShaderPass.hlsl file.

    No answers yet, but I'll keep digging.
     
    bobbaluba likes this.
  3. ElliotB

    ElliotB

    Joined:
    Aug 11, 2013
    Posts:
    27
    Ok, so I can get this to work if I manually include the ShaderPass.hlsl file at the start of my custom function

    Full Solution in 10.2:
    upload_2021-1-5_13-19-30.png

    Shadows.hlsl:
    Code (csharp):
    1. #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl"
    2.  
    3. inline void shadowcaster_float(out float _out) {
    4. #if ( SHADERPASS == SHADERPASS_SHADOWCASTER )
    5.     _out = 1.0;
    6. #else
    7.     _out = 0.0;
    8. #endif
    9. }
    10.  
    This will produce an object which is transparent yet still casts a shadow:
    upload_2021-1-5_13-21-17.png

    If you do not include the ShaderPass.hlsl file in the custom function, it does not work! So it seems to me that this is a bug, and that the ShaderPass include statement should occur higher up in the generated ShaderGraph file. (Perhaps this should be moved to the ShaderGraph forum?)
     
  4. ElliotB

    ElliotB

    Joined:
    Aug 11, 2013
    Posts:
    27
    Note that if you want backwards compatibility with previous render pipeline versions, you will need to switch based on the SRP version. There is also a bug there, so you will need to include Version.hlsl otherwise the VERSION_GREATER_EQUAL macro will not be defined in URP 10.2.

    Code (csharp):
    1. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Version.hlsl"
    2. #if VERSION_GREATER_EQUAL(10, 0)
    3. #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl"
    4. #endif
    5.  
    6. ... then in your function
    7.  
    8. #if VERSION_GREATER_EQUAL(10,0)
    9. #define SHADOWTEST ( SHADERPASS == SHADERPASS_SHADOWCASTER )
    10. #else
    11. #define SHADOWTEST defined(SHADERPASS_SHADOWCASTER)
    12. #endif
    13.  
    14. #if SHADOWTEST
    15.     //do something in shadowcaster pass
    16. #else
    17.     //do something in normal pass
    18. #endif
    19.  
     
    unity_IpxdANggCs1roQ likes this.
unityunity