11. Renderer Feature/Pass Collection of Practical Patterns (URP)
This chapter organizes “typical functions that can be implemented with Render Features” into patterns.
Preceding: 03. URP 아키텍처, 04. RenderGraph, 05. 텍스처/ID/핸들
11.1 Pattern 1: Copy Camera Color
Goal:
- Save the color buffer separately after opaque rendering
- Reference in later passes (post/transparent, etc.)
Key:
- RenderGraph:
CreateTexture+Blitpass - Legacy:
_CameraColorTextureUtilizes similar slots/RTHandle
RenderGraph Implementation Checklist
-What timing color is needed? (After Opaque? After Transparent?)
- Are the format/resolution/scale of the output texture the same as the camera color?
- Where will the results be “exposed” so that subsequent passes can access them?
- (A) Replace activeColor of
UniversalResourceData - (B) Bind to global slot (
SetGlobalTexture) (if necessary)
- (A) Replace activeColor of
11.2 Pattern 2: Depth/Normals based effects
Goal:
- Outline, SSAO, screen space effects
Key:
- Set URP to generate Depth/Normal textures
- Correctly sample that texture in the shader
Practical Checklist
- Are the requirements (Depth/Normal) set to be met?
- If you use the Full Screen Pass Renderer Feature, check it in Requirements.
- If it is a custom pass, declare the input request according to the URP document/source.
- Have you linearized the raw depth? (Based on
_ZBufferParams) - Have you checked whether the normal texture is world normal or view normal? (depends on URP implementation/setup)
Related: 08. URP HLSL 라이브러리 지도
11.3 Pattern 3: Custom Render Target (Off-screen Render)
Goal:
- Only specific layers/objects are rendered in separate RT
- Used for later synthesis/mask
Key:
- Culling/Draw Settings (FilteringSettings, DrawingSettings)
- Render target lifetime management (RTHandle/RenderGraph)
Structural points when doing offscreen rendering in RenderGraph
- It is safe to encapsulate “what to draw” in a RendererList (or similar concept).
- “Where to draw” is specified as
SetRenderAttachment. - “Which shader pass to use” is linked to
LightMode(or ShaderTagId) in ShaderLab Pass.
Once you learn this pattern:
- Create mask/ID buffer
- Custom Shadow/Special Depth Pass
- Render only specific objects in separate colors (minimap/portal/post-processing)
The same function can be implemented systematically.
11.4 Pattern 4: RenderGraph-based multi-pass (downsample chain)
Goal:
- Create blur/bloom/pyramid textures
Key:
- Connect dependencies between passes with handles
- Create/reuse temporary textures in multiple steps
Practical tips
- Downsample/upsample is a trade-off between bandwidth and filtering quality.
- If possible, design textures that use the same desc as clearly shared/reused so that RenderGraph can reuse resources.
11.5 Pattern 5: When using “global slot ID” with RenderGraph
Even though RenderGraph is central, Shader.PropertyToID + SetGlobalTexture is still useful in the following situations:
- Shader code is structured based on “global texture names” and major refactoring is difficult.
- Need to read specific global texture from ShaderGraph node
- Third-party shader expects a global texture with a specific name
The principles here:
- Check how to expose the backing of
TextureHandlecreated by RenderGraph to the outside (support varies depending on URP/version) - In Compatibility Mode, use the legacy pattern of creating a temporary RT and binding it to a global slot, but be sure to check lifespan management and multi-camera leaks.
Related: 05. 텍스처/ID/핸들
11.6 Pattern 6: Graph connectivity resistant to pass culling
Goal:
- Reduce “paths created but not executed” at the design stage
Key:
- Create a chain so that the output must be read in the next pass.
- The debug pass also temporarily connects the consumption path to verify survivability.
Checklist:
11.7 Pattern 7: Multi-camera/camera stack safety boots
Goal:
- Results remain consistent even when Base/Overlay/SceneView are mixed
Key:- Application conditions for each camera type are specified at AddRenderPasses
- Cameras without input resources (Depth/Normals/Post active or not) are early-out
- If there is a possibility of global slot conflict, local binding takes precedence.
Practical tips:
- Record the path to reproduce the problem by outputting the camera name/type to the log.
- Set “Apply game camera only” as default and gradually expand
11.8 Pattern 8: Debugging Loop (Feature Unit)
- Check if the pass is actually enqueued/executed with Frame Debugger
- Check read/write contract and resource lifetime with RenderGraph Viewer
- Check early-out path when input resources are not ready (Depth/Normals/MotionVectors)
- Check for global state conflicts in multi-camera
Sample reference:
samples/Unity6_Rendering_Bible/01_Architecture_and_Pipeline/04_URP_Renderer_Features_Design.mdsamples/Unity6_Rendering_Bible/04_Render_Graph_System/04_RenderGraph_Debugging_and_Culling.md