Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Supporting the URP and Built-In renderer in a single shader?

Discussion in 'Shaders' started by tcmicka, Dec 10, 2021.

  1. tcmicka

    tcmicka

    Joined:
    Aug 2, 2017
    Posts:
    8
    Hello,

    I've been using the "RenderPipeline" = "xyz" tag to author a single shader (file) that works across multiple render pipelines (specifically URP and built-in). For example, the top SubShader is used by the URP and the bottom SubShader is used by the built-in renderer:
    upload_2021-12-10_14-13-30.png

    This works marvelously in practice until the shader is used in a project that does not have the URP package installed. When that occurs, any URP includes can't be found and generate compilation errors:

    Shader error in 'LitPipelineTest': Couldn't open include file 'Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl'. at line 22


    This makes a fair bit of sense because the project does not contain those shaders includes. But it would be nice if the shader compile skipped compilation of any SubShaders tagged to work with pipelines that are not installed.

    My question is: Is the compilation error behavior by design? Or is this a bug? Or have I set this up incorrectly?

    Thank you!

    P.S. I've attached the LitPipelineTest.shader for more context.
     

    Attached Files:

    fuser likes this.
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    The tags are used by a given rendering pipeline to decide which version of a pass to use, they aren't able to affect the compilation as far as I'm aware.

    For some reason Unity also doesn't define any preprocessor macros for the pipelines when they're installed... At least as far as I can tell, but perhaps they have them hidden away unused. So you can't by default conditionally avoid that faulty include either...

    So I've made a script that makes some global keywords when a given package is installed, as well as when they are currently active: https://github.com/Invertex/Unity-A...ets/Plugins/SetShaderRenderPipelineKeyword.cs

    So then in your shader example there, we can use the keywords the script sets to conditionally include that URP file or not.

    Code (CSharp):
    1. Shader "LitPipelineTest"
    2. {
    3.     Properties
    4.     {
    5.         _Color("Color", Color) = (0.5, 0.5, 0.5, 1)
    6.     }
    7. //Include all the common stuff all our passes will be using here
    8.     HLSLINCLUDE
    9.         struct Attributes
    10.         {
    11.             float4 vertex : POSITION;
    12.             half3 normal : NORMAL;
    13.         };
    14.  
    15.         struct Varyings
    16.         {
    17.             float4 position : SV_POSITION;
    18.             half3 worldNormal : COLOR0;
    19.         };
    20. //Load diffierent include files based on if URP is installed or not
    21.         #if RP_URP_INSTALLED
    22.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    23.         #else
    24.             #include "UnityCG.cginc"
    25.         #endif
    26.  
    27.         CBUFFER_START(UnityPerMaterial)
    28.             half4 _Color;
    29.         CBUFFER_END
    30.  
    31. //Include different Vert/Frag programs depending on if URP is installed
    32.         #if RP_URP_INSTALLED
    33.             Varyings LitVertex(Attributes input)
    34.             {
    35.                 Varyings output;
    36.                 output.position = TransformObjectToHClip(input.vertex.xyz);
    37.                 output.worldNormal = TransformObjectToWorldNormal(input.normal);
    38.                 return output;
    39.             }
    40.  
    41.             half4 LitFragment(Varyings input) : SV_Target
    42.             {
    43.                 Light directionalLight = GetMainLight();
    44.                 half3 directionalLightDirection = directionalLight.direction;
    45.                 half3 directionalLightColor = directionalLight.color;
    46.                 half diffuse = max(dot(input.worldNormal, directionalLightDirection), 0);
    47.                 return half4(_Color.rgb * directionalLightColor * diffuse, 1);
    48.             }
    49.         #else
    50.             half4 _LightColor0;
    51.  
    52.             Varyings LitVertex(Attributes input)
    53.             {
    54.                 Varyings output;
    55.                 output.position = UnityObjectToClipPos(input.vertex);
    56.                 output.worldNormal = UnityObjectToWorldNormal(input.normal);
    57.                 return output;
    58.             }
    59.  
    60.             half4 LitFragment(Varyings input) : SV_Target
    61.             {
    62.                 half3 directionalLightDirection = _WorldSpaceLightPos0.xyz;
    63.                 half3 directionalLightColor = _LightColor0.rgb;
    64.                 half diffuse = max(dot(input.worldNormal, directionalLightDirection), 0);
    65.                 return half4(_Color.rgb * directionalLightColor * diffuse, 1);
    66.             }
    67.         #endif
    68.     ENDHLSL
    69.  
    70.         /// Sub Shader for the Universal Render Pipeline (URP).
    71.     SubShader
    72.     {
    73.         Tags{ "RenderPipeline" = "UniversalPipeline" "RenderType" = "Opaque" }
    74.  
    75.         Pass
    76.         {
    77.             Name "Main - URP"
    78.             Tags{ "LightMode" = "UniversalForward" }
    79.  
    80.             HLSLPROGRAM
    81.             //Compile URP installed variant
    82.             #pragma multi_compile RP_URP_INSTALLED
    83.             #pragma vertex LitVertex
    84.             #pragma fragment LitFragment
    85.             ENDHLSL
    86.         }
    87.     }
    88.     /// Sub Shader for the Built-in Render Pipeline.
    89.     SubShader
    90.     {
    91.         Tags { "RenderType" = "Opaque" "RenderPipeline" = ""}
    92.  
    93.         Pass
    94.         {
    95.             Name "Main - Built-in"
    96.             Tags{ "LightMode" = "ForwardBase" }
    97.  
    98.             HLSLPROGRAM
    99.         //Compile regular variant
    100.             #pragma multi_compile __
    101.             #pragma vertex LitVertex
    102.             #pragma fragment LitFragment
    103.             ENDHLSL
    104.         }
    105.     }
    106.         Fallback "Diffuse"
    107. }
    So all you have to do is include that script with your shader files. It's a little annoying though, there really should be a built-in define for this.
     
  3. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,844
  4. tcmicka

    tcmicka

    Joined:
    Aug 2, 2017
    Posts:
    8
    @Invertex thank you so much for the sample code. I too looked high and low for preprocessor definition for if SRPs are enabled/installed and found none. Maybe Unity is hesitant to pollute the global shader keyword space?

    @AleksandrKashkevich this is wonderful! Exactly what I was looking for. I just tested with my package (which fortunately requires 2020.3+) and it worked. Thank you!

    upload_2021-12-13_10-35-56.png
     

    Attached Files:

    fuser, zwcloud and aleksandrk like this.
  5. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    449
    Sorry, but this statement is misleading.
    Actually, it begins working somewhere between 2020.3.12 and 2020.3.18. I'm not sure I'm willing to download another 3 unity versions just to find out the exact spot...
    I develop an Asset Store plugin, so it's important for me to support the minimum possible version of Unity. That's why I tried 2020.3.0f1 at first and it was somewhat frustrating to find out that it doesn't work.

    So yeah, hope this clarification helps someone :)
     
    Last edited: Jun 5, 2023
  6. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,844
    It's 2020.3.16f1
     
    MUGIK likes this.