book/18-urp-lit-compatible-pass-template.md

18. URP fully compatible ShaderLab Pass set template

Based on Unity 6.3 (6000.3) / URP 17.3.0, it provides a ‘fully compatible’ Pass set template including Forward/ShadowCaster/DepthOnly/DepthNormals/Meta + (optional) GBuffer/MotionVectors/XR/2D

#18. URP fully compatible ShaderLab Pass set template

This chapter provides practical templates of custom shaders that “run as close to the URP built-in Lit environment as possible.”

Goal:

  • Provides all LightMode Passes expected by URP
  • Configure CBUFFER without breaking SRP Batcher compatibility
  • Provides basic framework including Forward+/additional light keywords

Predecessor:

VERY IMPORTANT (REAL WARNING)
“Fully compatible” is more demanding depending on project settings (Forward+/Deferred, SSAO, Decal, Rendering Layers, XR, etc.)
This template is based on the most common URP Lit compatibility set, you will need to add keywords/paths depending on your project functionality.

18.0 Accurate Reference (Generated, URP 17.3.0)

This chapter is not an “abstract template,” but is designed to be used with references automatically extracted from local URP 17.3.0 sources.

18.1 Template configuration file

This book repository includes the sample files below.

  • samples/urp/URP_LitCompatibleTemplate.shader
  • samples/urp/URP_LitCompatibleTemplate.hlsl

The document explains key parts, and the entire code refers to the sample file.

18.1.1 The safest strategy to change templates to “your custom Lit”

If you try to completely re-implement URP built-in Lit, there are more features involved than you might think (decals, GI, light layers, render layers, fog, lightmaps, probe volumes, debug displays, etc.).

Therefore, the recommended strategy is the following two steps:

  1. Step 1 (Fixing compatibility shell): Set Pass/Tags/CBUFFER/Keyword to be the same as URP Lit as much as possible.
  2. Step 2 (Minimize Replacement Points): Replace “only the surface model” first (e.g. albedo/normal/roughness processing), then “only the BRDF”.

This narrows down the cause of “why it broke” and makes debugging easier.

18.2 Meaning of Pass Set (Why do you need it?)

URP's Render Pass (C#) does the following in certain steps:

  • Decide “Which ShaderLab Pass to use in this step?” as LightMode

So, for a custom shader to participate in each step of URP:

  • You must provide the LightMode Pass that the step is looking for.
  • You must match the input (alpha clip/normal/depth, etc.) required by the pass.

18.3 Checklist for each pass (practical)

18.3.1 UniversalForward (color pass)

  • Includes keywords that support “features turned on in the project” such as main/additional lights, shadows, fog, GI, decals, etc.
  • When using Forward+, _CLUSTER_LIGHT_LOOP is included.
  • Material properties are fixed to UnityPerMaterial CBUFFER (same for all passes)

18.3.2 ShadowCaster

  • Alpha clip (cutout) processing
  • Compatible with URP methods such as shadow bias/normal offset

18.3.3 DepthOnly

  • Alpha clip (cutout) processing
  • Participate when DepthTexture creation is necessary

18.3.4 DepthNormals

  • Key to screen space effects (Outline/SSAO, etc.)
  • The space (WS/VS) where normals are stored must be tailored to the URP implementation.

18.3.5 Meta

  • For light map baking
  • Often only albedo/emission is needed

18.3.6 UniversalGBuffer (Optional, Deferred)

  • Virtually essential if your project uses Deferred rendering
  • LightMode = UniversalGBuffer
  • For the “same material” as ForwardLit to work in Deferred, it must meet the GBuffer output contract (albedo/normal/material parameters)

18.3.7 MotionVectors (optional, TAA/motion blur/reprojection)

  • TAA/motion blur/reprojection series functions may require a motion vector pass.
  • LightMode = MotionVectors
  • URP Lit configures the entry including ObjectMotionVectors.hlsl as #include_with_pragmas (be careful of missing pragmas)

18.3.8 XRMotionVectors (Optional, XR)- If motion vectors are required in XR, a separate contract may be required (e.g. stencil)

  • LightMode = XRMotionVectors
  • Based on URP Lit, it is similar to MotionVectors, but XR-specific define/Stencil blocks can be added.

18.3.9 Universal2D (Optional, 2D Renderer)

  • Additional passes may be required if 2D Renderer compatibility is required
  • LightMode = Universal2D
  • Must follow 2D-only Entry/Include(Utils/Universal2D.hlsl) contract

18.4 7 core rules for “URP Lit Compatible” templates

  1. Must include Tags { "RenderPipeline"="UniversalPipeline" }
  2. Provide LightMode Pass according to project needs (default: Forward/ShadowCaster/DepthOnly/DepthNormals/Meta + Option: GBuffer/MotionVectors/XR/2D)
  3. UnityPerMaterial Keep CBUFFER the same in all passes (SRP Batcher)
  4. Unify coordinates/screen/depth/lighting approach based on URP Core include
  5. When using Forward+, _CLUSTER_LIGHT_LOOP path is considered.
  6. Verify “pipeline inputs” such as Depth/Normals by connecting them to Requirements (whether created or not)
  7. Add “only necessary keywords” step by step to prevent variant explosion

18.4.1 Manage keyword sets by function (prevent variant explosion)

#pragma multi_compile explodes when trying to match URP Lit compatibility. To control this, it is best to manage them as “feature bundles”.

A) Light/Shadow

  • Additional Lights: _ADDITIONAL_LIGHTS_VERTEX, _ADDITIONAL_LIGHTS
  • Additional Light Shadows: _ADDITIONAL_LIGHT_SHADOWS
  • Main light shadows/cascade: _MAIN_LIGHT_SHADOWS, _MAIN_LIGHT_SHADOWS_CASCADE
  • Forward+: _CLUSTER_LIGHT_LOOP

B) Surface features

  • Alpha test: _ALPHATEST_ON
  • Normal map: _NORMALMAP
  • Parallax: _PARALLAXMAP

C) Environment

  • Fog: #pragma multi_compile_fog
  • Lightmap/SH: LIGHTMAP_ON etc. (according to project needs)

Recommended operation

  • In the template, only enter the “minimum set”,
  • Every time you turn on the project function, add only the necessary keywords,
  • Check accurately with Frame Debugger/RenderDoc.

18.5 Sample Code (Summary): ShaderLab Skeleton

Please refer to samples/urp/URP_LitCompatibleTemplate.shader for the full code.

ShaderLab
SubShader
{
    Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Opaque" "Queue"="Geometry" }

    Pass { Tags { "LightMode"="UniversalForward" } }
    Pass { Tags { "LightMode"="ShadowCaster" } }
    Pass { Tags { "LightMode"="DepthOnly" } }
    Pass { Tags { "LightMode"="DepthNormals" } }
    Pass { Tags { "LightMode"="Meta" } }

    // (옵션) Deferred
    Pass { Tags { "LightMode"="UniversalGBuffer" } }

    // (옵션) Motion Vectors
    Pass { Tags { "LightMode"="MotionVectors" } }
    Pass { Tags { "LightMode"="XRMotionVectors" } }

    // (옵션) 2D Renderer
    Pass { Tags { "LightMode"="Universal2D" } }
}

18.6 Sample Code (Summary): Fixing CBUFFER (SRP Batcher)

The key is “same layout in all passes”.

HLSL
CBUFFER_START(UnityPerMaterial)
float4 _BaseColor;
float4 _BaseMap_ST;
float _Cutoff;
CBUFFER_END

18.7 Order of applying templates to projects (recommended)

  1. In Forward+ OFF, first make Lit(Forward) operate normally
  2. Solve “Shadow/Depth” broken by adding ShadowCaster/DepthOnly
  3. Add DepthNormals to ensure “screen-based effects” compatibility
  4. Verify _CLUSTER_LIGHT_LOOP path after Forward+ ON
  5. If it is a deferred project, add/verify UniversalGBuffer pass
  6. Add/verify MotionVectors if you need TAA/motion blur/reprojection (and XRMotionVectors if XR) pass
  7. If 2D Renderer compatibility is required, add/verify Universal2D pass
  8. Add necessary functions (Decal/Rendering Layers/SSR, etc.) one by one

18.8 Verification routine (required): “Is the URP using my pass?”

Once you have added the template to your project, be sure to check the following:

  1. Watch rendering events with Frame Debugger and check which pass the object is drawn with.
  2. Verify that ForwardLit/ShadowCaster/DepthOnly/DepthNormals/Meta are called as expected
  3. If it is a deferred project, check whether GBuffer (UniversalGBuffer) is actually used.
  4. If TAA/motionblur/XR is involved, make sure MotionVectors/XRMotionVectors are actually used
  5. Check when Depth/Normals/History resources are created in RenderGraph Viewer

Once this verification is complete, you can start customizing (Surface Model/BRDF/Special Effects).