跳到主要内容

URP 渲染流程

这篇小笔记是对 Unity 官方文档中 Universal Render Pipeline 渲染流程 的一个中文梳理, 方便自己在看 URP 源码或写 ScriptableRendererFeature 时快速回忆整体结构。

官方文档原文:
https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.1/manual/rendering-in-universalrp.html

URP 的一次渲染大致可以拆成 5 个阶段:

  1. Setup Culling Parameters:准备剔除参数;
  2. Culling:根据参数和相机,计算本帧可见的 Renderer / Light / ShadowCaster;
  3. Build Rendering Data:把剔除结果和 URP Asset、Camera 等信息汇总成 RenderingData;
  4. Setup Rendering:基于 RenderingData 创建并排序 RenderPass 队列;
  5. Execute Renderer:按顺序执行各个 RenderPass,把结果输出到帧缓冲。

下面按步骤简单展开。


1. Setup Culling Parameters

目标: 决定本帧「剔除系统」工作时需要参考的各种参数。

典型会影响的内容包括:

  • 使用哪一台相机、视锥体多大;
  • 哪些 Layer 参与渲染 / 阴影计算;
  • 阴影距离、级联个数等 Shadow 相关设置;
  • 远裁剪平面、近裁剪平面,决定能看到多远的物体。

在 URP 源码里,这一步通常是:

  • Camera / UniversalAdditionalCameraData / QualitySettings 等读取配置;
  • 组装出一个 ScriptableCullingParameters
  • 提供出一个可覆写点(override),方便你在自定义管线里按需修改这些参数。

如果项目里需要做「只渲染某些层」「单独控制某帧阴影距离」之类的效果, 往往就是在这一步动手脚。


2. Culling

准备好剔除参数之后,就进入真正的 Culling 阶段。

在这一步中,渲染管线会:

  • 遍历场景中的 Renderer / Light / ShadowCaster;
  • 结合上一阶段设置好的视锥体、层过滤、阴影距离等参数;
  • 计算出「这一帧、这一台相机真正可见」的对象集合。

产物是一个 CullingResults,里面包含:

  • 可见物体列表(哪些 MeshRenderer / SkinnedMeshRenderer 需要被绘制);
  • 参与光照计算的光源;
  • 阴影相关数据(哪几个 ShadowCaster、如何生成 ShadowMap 等)。

剔除参数设置得越合理,渲染效率越高; 如果把阴影距离设得过大,则会导致很多看不到的物体仍然参与计算。


3. Build Rendering Data

完成 Culling 之后,URP 会开始构建本帧的 RenderingData

它会把多个来源的信息汇总起来:

  • 刚才得到的 CullingResults
  • URP Asset 上的全局设置(如渲染路径、MSAA、Shadow、附加光源数量等);
  • 当前 Camera 及其扩展组件上的设置(如后处理开关、渲染缩放比例、Viewport 等);
  • 当前运行平台(移动 / 桌面 / 主机)相关的质量和能力限制。

最终形成的 RenderingData 通常会拆分成几块结构:

  • CameraData:FOV、剪裁平面、View / Projection Matrix 等;
  • LightData:主光、附加光源、最大光源数等;
  • ShadowData:阴影贴图大小、级联数据、软阴影开关等;
  • 以及其他与渲染质量、后处理相关的配置。

可以简单理解为:
RenderingData 告诉整条渲染管线——这一帧要画什么、怎么画、用什么质量和效果。


4. Setup Rendering

有了 RenderingData 之后,接下来是 Setup Rendering 阶段。

核心工作:

  • 创建本帧需要的各种 ScriptableRenderPass
  • 根据类型和依赖关系,为这些 Pass 排好执行顺序;
  • 告诉管线:「这一帧先做哪些前置 Pass,再做主渲染,最后做后处理、UI 等等」。

常见的 Pass 类型包含:

  • 深度预通道(Depth Prepass);
  • 主光 / 附加光的前向渲染 Pass;
  • 阴影相关 Pass;
  • 不透明物体 / 透明物体的分组渲染 Pass;
  • 后处理与 UI 等特殊 Pass。

在自定义 Renderer 的时候, 你通常会在这里:

  • 调用 EnqueuePass 把自定义的 RenderPass 加入队列;
  • 或者根据 Camera / Platform 条件,决定是否启用某些 Pass。

这一步通常也是明显标注为「可重写」的阶段之一。


5. Execute Renderer

最后一个阶段是 Execute Renderer, 负责按顺序执行刚才排好的所有 RenderPass。

整体流程大致是:

  1. 初始化渲染目标(Camera Target 或自定义 RT);
  2. 依次执行各个 Pass 的 Execute
    • 设置 RenderTarget;
    • 清屏或保留上一帧结果;
    • 配置 Viewport / Scissor 等状态;
    • 调用 DrawRenderers / Blit 等命令真正发送 DrawCall;
  3. 所有 Pass 执行完毕后,把最终图像输出到帧缓冲供显示。

在 Frame Debugger 中看到的「一步步执行命令」 本质上就是这个阶段展开后的具体指令序列。


小结

从高层视角看,URP 的一次渲染循环可以概括为:

  1. 准备剔除参数(Setup Culling Parameters):决定谁有资格参与本帧渲染和阴影计算;
  2. 执行剔除(Culling):结合相机和参数,得到可见对象与光源;
  3. 构建渲染数据(Build Rendering Data):汇总 Culling 结果、URP Asset、Camera、平台信息;
  4. 搭建 Pass 队列(Setup Rendering):创建并排序本帧要执行的 RenderPass;
  5. 按顺序执行(Execute Renderer):逐个 Pass 下发指令,最终把画面输出到屏幕。

理解这 5 个阶段有助于:

  • 阅读 URP 源码时不迷路;
  • 在写 ScriptableRendererFeature 时知道该挂在哪一步;
  • 调整 URP Asset / Camera 设置时,清楚它们会影响流程的哪一段。

版权声明:本文最初发布于 CSDN「uniGame」,遵循 CC 4.0 BY-SA 协议,转载请附上原文链接及本声明。
原文链接:https://blog.csdn.net/alla_Candy/article/details/121559633