#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.
- Pass/Include map: @@TOK_0_14164784@@
- Pass contract table (when/why consumed): @@TOK_1_b865c9ce@@
- Lit core symbol xref: @@TOK_2_8394c928@@
18.1 Template configuration file
This book repository includes the sample files below.
samples/urp/URP_LitCompatibleTemplate.shadersamples/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:
- Step 1 (Fixing compatibility shell): Set Pass/Tags/CBUFFER/Keyword to be the same as URP Lit as much as possible.
- 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
LightModePass 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_LOOPis included. - Material properties are fixed to
UnityPerMaterialCBUFFER (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.hlslas#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
- Must include
Tags { "RenderPipeline"="UniversalPipeline" } - Provide LightMode Pass according to project needs (default: Forward/ShadowCaster/DepthOnly/DepthNormals/Meta + Option: GBuffer/MotionVectors/XR/2D)
UnityPerMaterialKeep CBUFFER the same in all passes (SRP Batcher)- Unify coordinates/screen/depth/lighting approach based on URP Core include
- When using Forward+,
_CLUSTER_LIGHT_LOOPpath is considered. - Verify “pipeline inputs” such as Depth/Normals by connecting them to Requirements (whether created or not)
- 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_ONetc. (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.shaderfor the full code.
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”.
CBUFFER_START(UnityPerMaterial)
float4 _BaseColor;
float4 _BaseMap_ST;
float _Cutoff;
CBUFFER_END
18.7 Order of applying templates to projects (recommended)
- In Forward+ OFF, first make Lit(Forward) operate normally
- Solve “Shadow/Depth” broken by adding ShadowCaster/DepthOnly
- Add DepthNormals to ensure “screen-based effects” compatibility
- Verify
_CLUSTER_LIGHT_LOOPpath after Forward+ ON - If it is a deferred project, add/verify
UniversalGBufferpass - Add/verify
MotionVectorsif you need TAA/motion blur/reprojection (andXRMotionVectorsif XR) pass - If 2D Renderer compatibility is required, add/verify
Universal2Dpass - 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:
- Watch rendering events with Frame Debugger and check which pass the object is drawn with.
- Verify that ForwardLit/ShadowCaster/DepthOnly/DepthNormals/Meta are called as expected
- If it is a deferred project, check whether GBuffer (UniversalGBuffer) is actually used.
- If TAA/motionblur/XR is involved, make sure MotionVectors/XRMotionVectors are actually used
- 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).
18.8 Read next
- Find Lit include chain/function location: 16. URP Lit 실제 맵
- Screen-based effects with Compute/UAV: 17. RenderGraph Compute/UAV 패턴