book/21-urp-hlsl-structs-dataflow.md

21. URP HLSL Structs & Dataflow

In Unity 6.3 (6000.3) / URP 17.3.0, dissect VertexPositionInputs/VertexNormalInputs/SurfaceData/InputData/Light by field and fix “who fills it and where it is written” by data flow.

21. URP HLSL Structs & Dataflow (URP 17.3.0)

The most powerful criterion for studying URP shaders “correctly” is the struct.

  • Functions come and go, but data contracts (structure fields and meaning) persist longer.
  • In particular, in the Lit series, SurfaceData and InputData are effectively “pipeline interfaces.”

This chapter aims to:

  1. Rather than memorizing structure fields, connect meaning/space/producer/consumer.
  2. LitPassFragment → UniversalFragmentPBR Describe the data flow “by field.”
  3. When debugging, make it a habit to narrow down the cause to “which field is empty.”

21.0 Accurate Reference (Generated)

Primary source for structure definition/field list:

Function signature (to keep track of who fills it):

Lit core symbol xref (definition + representative caller):

21.1 Lit data flow (big picture)

If you look at Lit Forward as a data flow, it is as follows.

Parse error on line 1:
flowchart TD  A[Att
^
Expecting 'NEWLINE', 'SPACE', 'GRAPH', got 'ALPHA'

The “accurate reference” for this flow is further narrowed down and fixed in Chapter 16/22.

21.2 VertexPositionInputs: Location (WS/VS/CS/NDC) Agreement

Definition (URP 17.3.0):

Generate function:

  • VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
    • <URP>/ShaderLibrary/ShaderVariablesFunctions.hlsl:8

Field:

Field Type meaning State Consumer Agency
positionWS float3 World coordinates Lighting/Shadow/Cluster (Forward+)
positionVS float3 View (camera) coordinates Depth-based calculations/special effects
positionCS float4 clip coordinates rasterizer input (final)
positionNDC float4 Normalized Device Coordinates (NDC) Screen UV calculation, etc.

Practical tips:

  • “Forward+ cluster loop” consumes positionWS and normalizedScreenSpaceUV very frequently.
  • It is difficult to debug a shader that is only created by positionCS. If possible, use GetVertexPositionInputs in URP as a starting point.

21.3 VertexNormalInputs: tangent basis contract (WS tangent/bitangent/normal)

Definition (URP 17.3.0):

  • <URP>/ShaderLibrary/Core.hlsl:267

Generating function (representative):

  • VertexNormalInputs GetVertexNormalInputs(float3 normalOS)
    • <URP>/ShaderLibrary/ShaderVariablesFunctions.hlsl:22
  • VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS)
    • <URP>/ShaderLibrary/ShaderVariablesFunctions.hlsl:31

Field:

Field Type meaning State Consumer Agency
tangentWS real3 World space tangent Normal map/tangent space transformation
bitangentWS real3 World space bitangent Normal map/tangent space transformation
normalWS float3 World space normal Light/BRDF/Shadow

Practical tips:

  • “Normal is flipped/highlight is strange” is mostly a tangent basis problem.
  • normalWS consumes virtually everywhere in light loops/shadows/indirect lighting (most expensive bug).

21.4 SurfaceData: Material (surface) input contract

Definition (URP 17.3.0):

  • <URP>/ShaderLibrary/SurfaceData.hlsl:5

Commonly filled functions in Lit:

  • InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)
    • <URP>/Shaders/LitInput.hlsl:252

Field:

Field Type Meaning (Summary) State Consumer Agency
albedo half3 Base color (texture/color product result) PBR
specular half3 specular color (specular workflow) PBR
metallic half Metallic (Metallic Workflow) PBR
smoothness half Smoothness (reciprocal roughness series) PBR
normalTS half3 Tangent space normal (normal map result) Configure InputData
emission half3 Self-luminous final color
occlusion half Occlusion Light Attenuation
alpha half Alpha (transparent/cutout) OutputAlpha
clearCoatMask half Clear coat mask PBR (optional)
clearCoatSmoothness half Clearcoat Smoothness PBR (optional)

Practical tips (safe customization):

  • Step 1 of “Change my material model” is to adjust the SurfaceData value.
  • This step is relatively independent from the Pass contract/light loop/Forward+ branch, making it easy to maintain compatibility.

21.5 InputData: Space/Camera/Lighting Preparation Agreement (Core)

Definition (URP 17.3.0):- <URP>/ShaderLibrary/Input.hlsl:43

Commonly filled functions in Lit Forward:

  • InitializeInputData(Varyings input, half3 normalTS, out InputData inputData)
    • <URP>/Shaders/LitForwardPass.hlsl:72

Fields (23 total, based on Generated):

The table below is for viewing “field meaning + usually who fills it and where it is used” at a glance.
Which fields are actually populated may depend on project features (Decal/APV/Debug/ProbeVolumes, etc.) and keywords.

Field Type meaning/space Main producer (representative) State Consumer Agency (Representative)
positionWS float3 World Location InitializeInputData Light/Shadow/Cluster
positionCS float4 clip location Varyings/Pass LODFade/Decal etc.
normalWS float3 World normal (normalization required) InitializeInputData PBR/Shadow
viewDirectionWS half3 World view orientation (usually normalized) InitializeInputData PBR
shadowCoord float4 Main light shadow coordinates GetShadowCoord etc. Shadow Sampling
fogCoord half fog coefficient InitializeInputData MixFog
vertexLighting half3 vertex additional lighting stacked vertex path Final color (optional)
bakedGI half3 baked GI(LM/APV/SH) InitializeBakedGIData PBR
normalizedScreenSpaceUV float2 0..1 screen UV GetNormalizedScreenSpaceUV etc. Forward+ (cluster), SSR type
shadowMask half4 shadowmask/probe occlusion GI/Lightmap Path shadow mixing
tangentToWorld half3x3 TS→WS basis InitializeInputData normalTS conversion
dynamicLightmapUV half2 Dynamic Lightmap UV vertex path GI
staticLightmapUV half2 static lightmap UV vertex path GI
vertexSH float3 SH(vertex) vertex path GI
brdfDiffuse half3 BRDF diffuse cache (optional) PBR Preparation PBR
brdfSpecular half3 BRDF specular cache (optional) PBR Preparation PBR
uv float2 UV for original/tracking (optional) Debug/Function Debug/VT etc.
mipCount uint number of mips (optional) VT/Streaming Debug
texelSize float4 texel size (optional) VT/Streaming Debug
mipInfo float4 mip information (optional) VT/Streaming Debug
streamInfo float4 Streaming Information (Optional) VT/Streaming Debug
originalColor float3 Original color (optional) Debug/Post-Processing Debug
probeOcclusion float4 Probe occlusion (optional) probe/APV shadow mixing

Practical tips:

  • If normalizedScreenSpaceUV is empty in Forward+, the cluster light loop does not work properly.
  • shadowCoord is the key input of “Main Light Shadow”. If the direction/space is misaligned, the entire shadow will be broken.

21.6 Light: Light summary (light consumption contract)

Definition (URP 17.3.0):

  • <URP>/ShaderLibrary/RealtimeLights.hlsl:12

Field:

Field Type Meaning (Summary)
direction half3 Light direction
color half3 Light color/intensity
distanceAttenuation float Distance Attenuation
shadowAttenuation half Shadow Attenuation
layerMask uint light layer matching

Core API combined with Forward+ loop:

21.7 Common mistakes (data flow perspective)1) Space confusion: Mixing normalTS/normalWS and positionCS/positionNDC

  1. Missing normalization: Specular is broken due to normalWS, viewDirectionWS not being normalized
  2. Forward+ input missing: normalizedScreenSpaceUV is empty, cluster loop fails
  3. DepthNormals contract not involved: SSAO/Outline reads empty texture

A quick practical debugging routine can be found in the following chapters.