book/16-urp-shaderlibrary-lit-include-chain.md

16. URP ShaderLibrary actual map: Lit-based include chain

In Unity 6.3 (6000.3) + URP (17.x), map ‘actual source base’ which HLSL files/functions/keywords are connected based on Lit.shader.

The goal of this chapter is to help you answer the following questions “without losing track.”

  • What paths (LightMode) does URP Lit.shader consist of?
  • Which .hlsl does each pass include, and which entry functions (vertex/fragment) are defined there?
  • From which file do functions like TransformObjectToHClip, GetMainLight, UniversalFragmentPBR come from?

Very important
In URP, the file configuration/function names change slightly when the package version changes.
This document is designed to help you understand by fixing the “role/connection structure” based on **URP Lit, and to do the final verification using the local package source.

16.0 Accurate Reference (IDE, URP 17.3.0)

The “accuracy anchor” for this chapter is the IDE surface below.

Principle: For “Definition location (file/line)”, IDE Index is the first answer.
The context (why it is implemented that way) is read by opening the local URP/Core source.

Predecessor:

16.1 First, let’s fix the version (the reality of “Unity 6.3”)

Unity 6.3 usually means the editor version 6000.3.*, but the shader include chain is determined by the URP package version.

Practice check:

  1. Check the com.unity.render-pipelines.universal version in Package Manager.
  2. Open the local package source (Packages/ or Library/PackageCache/) to check actual file

Related: 01. 큰그림

16.2 Lit.shader is a “pass bundle” (URP 17.3.0: 9 LightMode types)

URP Lit.shader consists of a bundle of several ShaderLab Passes to allow “Lit Materials” to participate in multiple stages of the pipeline.

There are 9 LightMode Passes below in Lit.shader in URP 17.3.0 (see @@TOK_16_14164784@@ for exact list/include).

Pass NameLightModeWhen is it consumed (Summary)
ForwardLitUniversalForwardDefault Forward color (including Forward+)
GBufferUniversalGBufferGBuffer output in deferred rendering
ShadowCasterShadowCasterShadow map rendering
DepthOnlyDepthOnlyCamera Depth/Depth Freepass
DepthNormalsDepthNormalsDepth+Normals texture creation (SSAO/Outline based)
MetaMetaFor lightmap baking
MotionVectorsMotionVectorsObject motion vector (velocity)
XRMotionVectorsXRMotionVectorsXR Motion Vector (+Stencil Agreement Included)
Universal2DUniversal2D2D Renderer Compatibility Pass

These passes are selected when URP’s Render Pass (=C# pipeline stage) looks for a “ShaderLab Pass with a specific LightMode”.

Related: 09. URP 호환 셰이더 작성

16.3 Lit standard “include chain” large map

The inclusion of Lit shaders is stable if you think of them as three layers.1. Core layer (base): Coordinate transformation/platform macro/utility/definition 2. Functional Layer (Input/Lighting/Shadow/GI): Light Access, BRDF, Shadow Sampling, Lightmap/Probe. 3. Pass layer (entry): vertex/fragment entry function of Forward/Depth/Shadow/Meta

16.3.1 Chain as Mermaid (Concept Map)

This graph represents “what roles are connected to where”.
The exact file name may be different in the URP version, so follow the graph and check in your local package.

graph TD LitShader["Lit.shader (ShaderLab)"] %% Pass blocks (LightMode) ForwardPass["ForwardLit (UniversalForward)"] GBufferPass["GBuffer (UniversalGBuffer)"] ShadowPass["ShadowCaster (ShadowCaster)"] DepthOnlyPass["DepthOnly (DepthOnly)"] DepthNormalsPass["DepthNormals (DepthNormals)"] MetaPass["Meta (Meta)"] MotionPass["MotionVectors (MotionVectors)"] XRMotionPass["XRMotionVectors (XRMotionVectors)"] Pass2D["Universal2D (Universal2D)"] %% URP pass HLSL (entry/include roots) LitForward["LitForwardPass.hlsl (LitPassVertex/LitPassFragment)"] LitGBuffer["LitGBufferPass.hlsl (LitGBufferPassVertex/LitGBufferPassFragment)"] LitInput["LitInput.hlsl (Surface/Material 입력)"] LitMeta["LitMetaPass.hlsl (Meta 엔트리)"] LitDepthNormals["LitDepthNormalsPass.hlsl (DepthNormals 엔트리)"] DepthOnlyHlsl["DepthOnlyPass.hlsl (DepthOnly 엔트리)"] ShadowCasterHlsl["ShadowCasterPass.hlsl (ShadowCaster 엔트리)"] ObjectMotion["ObjectMotionVectors.hlsl (MotionVectors 엔트리)"] Universal2D["Utils/Universal2D.hlsl (2D 엔트리)"] %% Core/Lighting Core["Core.hlsl / SpaceTransforms / UnityInput"] Surface["SurfaceInput.hlsl (BaseMap/NormalMap 등)"] Lights["Lighting.hlsl / RealtimeLights.hlsl"] Shadows["Shadows.hlsl"] GI["GlobalIllumination.hlsl (SAMPLE_GI 등)"] LitShader --> ForwardPass --> LitForward LitShader --> GBufferPass --> LitGBuffer LitShader --> ShadowPass --> ShadowCasterHlsl LitShader --> DepthOnlyPass --> DepthOnlyHlsl LitShader --> DepthNormalsPass --> LitDepthNormals LitShader --> MetaPass --> LitMeta LitShader --> MotionPass --> ObjectMotion LitShader --> XRMotionPass --> ObjectMotion LitShader --> Pass2D --> Universal2D LitForward --> LitInput LitGBuffer --> LitInput ObjectMotion --> LitInput Universal2D --> LitInput LitForward --> Core LitForward --> Surface LitForward --> Lights LitForward --> Shadows LitForward --> GI

Based on this map, we keep track of where the functions are coming from.

16.4 “Entry functions” and main responsibilities for each pass (URP 17.3.0)

The most important thing in a URP shader is “which entry/output each pass is responsible for (= contract).”

Pass NameLightModeEntry (Representative)Core Responsibilities (Summary)
ForwardLitUniversalForwardLitPassVertex / LitPassFragmentSurfaceData/InputData configuration → PBR synthesis → Fog/Alpha → SV_Target* output
GBufferUniversalGBufferLitGBufferPassVertex / LitGBufferPassFragmentGBuffer output for Deferred
ShadowCasterShadowCasterShadowPassVertex / ShadowPassFragmentShadow map depth recording (+alpha clip/bias)
DepthOnlyDepthOnlyDepthOnlyVertex / DepthOnlyFragmentdepth recording (+alpha clip)
DepthNormalsDepthNormalsDepthNormalsVertex / DepthNormalsFragmentdepth+normal recording (based on SSAO/outline)
MetaMetaUniversalVertexMeta / UniversalFragmentMetaLitMeta output for baking (albedo/emission centered)
MotionVectorsMotionVectors(entry provided by ObjectMotionVectors)velocity output (ColorMask RG)
XRMotionVectorsXRMotionVectors(entry provided by ObjectMotionVectors)XR velocity output (+stencil contract)
Universal2DUniversal2Dvert / frag(Universal2D)2D Renderer compatible color path

Practical points
“Fully compliant” is not just ForwardLit, it is providing a LightMode Pass that the project actually consumes.
Contract full table (when/why consumed): @@TOK_24_b865c9ce@@

Related: 09. URP 호환 셰이더 작성

16.5 Fixing Lit Forward (UniversalForward) to the “correct reference”

Lit Forward is the most customized area in URP, so it is recommended that the symbols below be fixed to the signature/return value/definition position.

Original: @@TOK_25_8394c928@@

16.5.1 Key symbols (return value/definition location)

SymbolReturnsParams (Summary)Defined-in
TransformObjectToHClipfloat4float3 positionOS<CORE>/ShaderLibrary/SpaceTransforms.hlsl:108
LitPassVertexVaryingsAttributes input<URP>/Shaders/LitForwardPass.hlsl:158
LitPassFragmentvoidout SV_Target* output<URP>/Shaders/LitForwardPass.hlsl:223
InitializeStandardLitSurfaceDatavoidfloat2 uv, out SurfaceData<URP>/Shaders/LitInput.hlsl:252
InitializeInputDatavoidVaryings, normalTS, out InputData<URP>/Shaders/LitForwardPass.hlsl:72
UniversalFragmentPBRhalf4InputData, SurfaceData<URP>/ShaderLibrary/Lighting.hlsl:282

16.5.2 Why LitPassFragment is not half4 return: out SV_Target(MRT/Rendering Layers)

In URP 17.3.0, LitPassFragment outputs SV_Target0 (and the conditional SV_Target1) as an out parameter instead of the return value.

  • Definition: <URP>/Shaders/LitForwardPass.hlsl:223

This form:

  • Maintain scalable form with MRT (Multiple Render Target Output),
  • It is easy to attach additional output when features such as Rendering Layers are turned on.
  • Increases the likelihood that “fully compatible” custom shaders will be combined with URP features.### 16.5.3 Lit Forward call flow (step fixation)

The URP Lit Forward fragment is roughly structured in the following order (the exact call point is fixed by the IDE Index):

  1. InitializeStandardLitSurfaceData — Construct SurfaceData with UV/Texture
  2. InitializeInputData — Configuring InputData with Varyings/normalTS
  3. (Optional) Combining peripheral functions such as Decal/GI/APV
  4. UniversalFragmentPBR — Main/Additional Light/Shadow/GI Composition
  5. Output SV_Target* after post-processing MixFog, OutputAlpha, etc.
flowchart TD A[LitPassFragment] --> B[InitializeStandardLitSurfaceData] B --> C[InitializeInputData] C --> D{Feature hooks} D -->|Decal| E[ApplyDecalToSurfaceData] D -->|Baked GI| F[InitializeBakedGIData] E --> G[UniversalFragmentPBR] F --> G G --> H[MixFog / OutputAlpha] H --> I[SV_Target0 outColor]

16.5.4 Forward+ loop branch (summary)

In Forward+, the additional light loop contract is different.

  • GetAdditionalLightsCount() can return 0 (contract).
    • Definition: <URP>/ShaderLibrary/RealtimeLights.hlsl:271
  • URP simultaneously satisfies the Forward/Forward+ loop with LIGHT_LOOP_BEGIN/END.
    • Definition: <URP>/ShaderLibrary/RealtimeLights.hlsl:28 / :36

More details/debugging routines: 07. Forward/Forward+/Lights

16.6 SurfaceData vs InputData: “What do you put where?”

The best way to understand URP Lit is to separate these two structures and memorize them.

16.6.1 SurfaceData (Surface/Material input)

SurfaceData is information about “what surface the material is.”

  • Albedo (Base Color/Base Map)
  • Normal Map
  • Metallic/Smoothness/Occlusion/Emission
  • Alpha/Cutoff

In other words, texture sampling and organizing material parameters are key.

16.6.2 InputData (space/camera/light input)

InputData is information “where that surface is in the scene and under what camera/lighting conditions.”

  • positionWS / normalWS / viewDirectionWS -shadowCoord -fogCoord
  • bakedGI / shadowMask -normalizedScreenSpaceUV

In other words, space/coordinates/camera/shadow/GI preparation is key.

Understanding this separation:

  • “I want to change the surface model” → SurfaceData creation/transformation page
  • “I want to change the lighting calculation” → PBR function or light access side
  • “Depth/Screen UV is needed” → InputData/Core Utility page

You can quickly get your bearings.

This book is meant to be studied against the original package source, so the recommended workflow is to regenerate viewer-v2 data and then inspect include/symbol/xref results inside the IDE.

  • One-click runner: tools/generate-all.mjs
  • Generated data root: book/public/generated/<version>/viewer-v2/
  • Usage/docs entry: @@TOK_8_396718ca@@

tools/generate-all.mjs does the following in order:

  1. Generate viewer-v2 manifest/file/chunk data
  2. Validate the schema 4 output
  3. Explore the results through @@TOK_10_14164784@@, @@TOK_12_8394c928@@, and @@TOK_8_396718ca@@

Run (example):

Terminal window
node tools/generate-all.mjs --unity-project-root "<YOUR_UNITY_PROJECT_ROOT>"

The generated data does not expose absolute paths directly; it replaces them with <URP> and <CORE>.

Note
Manual maintenance helpers are being separated under tools/manual/** and are not part of the default pipeline.
Use tools/generate-all.mjs or pnpm gen:all as the default refresh routine.

16.8 What should we watch next?

  1. Run tools/generate-all.mjs and open @@TOK_4_14164784@@.
  2. Look at the include list in the ForwardLit (UniversalForward) section.
  3. Trace the following from @@TOK_6_8394c928@@ to “Definition location → Call destination”.
    • LitPassFragment
    • InitializeStandardLitSurfaceData
    • InitializeInputData
    • UniversalFragmentPBR
  4. Use the Frame Debugger to check “when DepthNormals pass is called” in the actual frame.