Skip to main content

๐Ÿ–ผ๏ธ Lesson 5.1: The URP Frame & the Frame Debugger

In Intermediate you authored materials with Shader Graph and never had to think about how a frame is drawn. This module goes below that line โ€” HLSL, custom passes, compute. But before you change the rendering, you have to see it. This lesson maps the anatomy of a single URP frame and hands you the tool that lets you step through it draw by draw: the Frame Debugger.

๐ŸŽฏ Learning Objectives

By the end of this lesson, you will be able to:

  • Explain what the Scriptable Render Pipeline is and how URP renders per camera
  • Name the major render passes of a URP frame and their order
  • Identify the RenderPassEvent injection points where custom work can hook in
  • Use the Frame Debugger to step through every draw call in a frame
  • Read a frame to diagnose overdraw, batching, and pass ordering

Estimated Time: 60 minutes  ยท  Prerequisite: Intermediate Shader Graph & URP lighting; Module 2 Lesson 2.4 (batching)

In This Lesson

The Scriptable Render Pipeline

Unity's rendering is a Scriptable Render Pipeline (SRP) โ€” the whole "how to draw a frame" process is written in C# rather than baked into the engine. The Universal Render Pipeline (URP) is one such pipeline, tuned for a wide range of platforms; HDRP is another, tuned for high fidelity. Because it's code, you can read it, hook into it, and extend it โ€” which is exactly what this module does.

Each frame, for each active camera, URP does a culling pass (which objects and lights are visible?) and then executes an ordered list of render passes that fill in the final image. Understanding that ordered list is the key that unlocks everything else โ€” a custom shader runs inside one of those passes, and a custom Renderer Feature adds one.

๐Ÿ“– Definition

A render pass is one self-contained step that reads and writes render textures โ€” "draw all opaque objects," "draw the skybox," "apply post-processing." A frame is the ordered sequence of passes that turns a culled scene into the pixels on screen.

The Passes of a URP Frame

A typical URP frame runs these passes in order. The exact set depends on your renderer settings (a depth prepass, SSAO, decals, etc. may be added), but the backbone is consistent:

The ordered render passes of a URP frame Left to right: render shadow maps, then depth/normals prepass (optional), then draw opaque geometry, then the skybox, then transparent geometry back-to-front, then post-processing, then final blit to the screen. Arrows show the order. One URP frame, per camera Shadowmaps Depth /Normals(optional) Opaquegeometry Skybox Transparentback-to-front Post-processing Finalblit front-to-back (early-Z saves fill) sorted for correct blending Custom passes inject between these stages via RenderPassEvent (next section).
Figure 1: The backbone of a URP frame. Opaques draw front-to-back (so hidden pixels are cheaply rejected); transparents draw back-to-front (so blending is correct); post-processing runs last on the finished colour.

Two ordering facts matter constantly. Opaque geometry is drawn roughly front-to-back so the depth test rejects hidden pixels before they're shaded (cheap). Transparent geometry must be drawn back-to-front and can't rely on the depth buffer the same way, which is why transparency is more expensive and why overdraw hurts most there.

RenderPassEvent Injection Points

The gaps between those passes are named, and a custom pass declares where it runs by setting a RenderPassEvent. You'll use these constantly in Lesson 5.3:

RenderPassEventRunsโ€ฆGood for
BeforeRenderingOpaquesbefore opaque geometryclearing/preparing custom buffers
AfterRenderingOpaquesafter opaques, before skyboxeffects on solid geometry (outlines)
BeforeRenderingTransparentsbefore transparent geometryrefraction grabs, distortion setup
BeforeRenderingPostProcessingafter transparents, before postfull-screen effects (blur, grade)
AfterRenderingPostProcessingafter post, near the endUI-space or final overlays

Picking the right event is half of writing a Renderer Feature correctly โ€” inject a full-screen colour effect at BeforeRenderingPostProcessing, not before the objects it's supposed to affect have even been drawn.

The Frame Debugger

The Frame Debugger (Window โ–ธ Analysis โ–ธ Frame Debugger) freezes a frame and lets you step through every draw event in order, showing the screen build up one call at a time. It's the single best tool for understanding โ€” and diagnosing โ€” what your renderer is actually doing.

The Frame Debugger window A recreation of Unity's Frame Debugger. On the left, an event tree lists the render passes and their draw calls: RenderShadows, DrawOpaqueObjects with several SRP Batch entries, DrawSkybox, DrawTransparentObjects, and a Post-processing Uber pass. A highlighted DrawOpaqueObjects event is selected. On the right, a details panel shows the selected draw's shader, pass, and output target, plus a note that 428 of 500 draws were batched. Frame Debugger Enable event 214 / 512 โ–พ RenderShadows Shadows.Draw ร—3 โ–พ DrawOpaqueObjects RenderLoop.Draw โ€” SRP Batch (128) SRP Batch (96) SRP Batch (204) โ–ธ DrawSkybox โ–พ DrawTransparentObjects Draw โ€” particles Draw โ€” glass โ–พ Render Post-processing UberPost (bloom + tonemap) โ–ธ FinalBlit โ† โ†’ arrows step through events Selected: DrawOpaqueObjects โ€” SRP Batch Shader: Universal Render Pipeline/Lit Pass: ForwardLit Output: _CameraColorAttachmentA Blend: One Zero ยท ZTest LEqual ยท ZWrite On Draw calls in batch: 128 โœ“ 428 of 500 opaque draws were SRP-batched 72 broke batch โ€” different shader variants / material keywords. Fixing those is a Module 2.4 batching win. Preview of the frame up to this event: the screen builds up one draw at a time as you step through the event list.
Figure 2: The Frame Debugger (faithfully recreated). The event tree on the left is your frame's pass list; selecting a draw shows its shader, pass, render target, and how many draws batched together.

Reading a Frame

Step through a frame and you can answer questions that are otherwise guesswork:

  • Is my batching working? If 500 opaque objects show up as 500 separate draws instead of a few SRP Batches, something is breaking the batch (a material keyword, an incompatible shader) โ€” the diagnosis you set up in Lesson 2.4.
  • What's the draw order? Watch the screen fill in; if a custom effect appears before the objects it should modify, your RenderPassEvent is wrong.
  • Where's my overdraw? Transparent objects stacking up (particles, foliage) each add a full-screen-ish draw โ€” the Frame Debugger makes the pile visible.
  • Which render target? Each event names the texture it writes (_CameraColorAttachmentA, a shadow map, a temp RT) โ€” essential when you start creating your own targets in Lesson 5.3.
๐Ÿ’ก Habit worth forming. Whenever a rendering result looks wrong, open the Frame Debugger first. Nine times in ten the ordered event list shows you exactly which pass misbehaved, before you touch a line of shader code.

What's Ahead

You now have the map. The rest of Module 5 fills it in:

  • Lesson 5.2 โ€” write the code that runs inside the opaque/transparent passes: HLSL shaders.
  • Lesson 5.3 โ€” add your own passes at those RenderPassEvent injection points: Scriptable Renderer Features.
  • Lesson 5.4 โ€” do general-purpose GPU work outside the draw passes entirely: compute shaders.
  • Lesson 5.5 โ€” combine features and shaders into a custom full-screen post-process effect.

Every one of them lives somewhere on Figure 1. Keep that diagram in mind and the module stays concrete.

Hands-on Challenge

๐Ÿ‹๏ธ Exercise 1: Dissect a real frame

Objective: Get fluent with the Frame Debugger.

  1. Open a scene with a handful of lit objects, some transparent particles, and post-processing (bloom).
  2. Open Window โ–ธ Analysis โ–ธ Frame Debugger and press Enable.
  3. Step from the first event to the last with the arrow keys. Note where shadows are drawn, where opaques finish and the skybox appears, and where post-processing kicks in.
  4. Find one opaque draw and read its shader/pass/output; find how many objects batched together.
๐Ÿ’ก What to look for

The event tree mirrors Figure 1: RenderShadows โ†’ DrawOpaqueObjects โ†’ DrawSkybox โ†’ DrawTransparentObjects โ†’ post โ†’ FinalBlit. If your opaques are one or two SRP Batches, batching is healthy; if they're dozens of individual draws, note which material/shader is breaking it.

๐ŸŽฏ Quick Quiz

Question 1: Why are opaque objects drawn front-to-back?

Question 2: You want a full-screen colour effect applied after all geometry but before bloom/tonemapping. Which RenderPassEvent?

Question 3: The Frame Debugger shows 500 opaque objects as 500 separate draws. What does that indicate?

Summary

๐ŸŽ‰ Key Takeaways

  • URP is a Scriptable Render Pipeline โ€” the frame is C# you can read and extend, run per camera after culling.
  • A frame's backbone: shadows โ†’ (depth) โ†’ opaque โ†’ skybox โ†’ transparent โ†’ post โ†’ final blit.
  • Opaques draw front-to-back (early-Z); transparents draw back-to-front (correct blending, more overdraw).
  • RenderPassEvent names the injection points where custom passes hook in โ€” choosing the right one is half the battle.
  • The Frame Debugger steps through every draw call โ€” your first stop for batching, ordering, overdraw, and render-target questions.

๐Ÿš€ What's Next?

You can see the frame; now you'll write the code that runs inside it. In Lesson 5.2: Writing Shaders in HLSL we leave Shader Graph behind and author a real URP shader by hand โ€” vertex and fragment stages, the URP shader library, and a genuine render of the result.

๐Ÿ–ผ๏ธ You can read a frame now

Passes in order, injection points between them, and a debugger to step through it all. Everything else in this module is a variation on that one picture.