[toc]

# Gbuffer 流程

先看一下 URP 在 Deffered 渲染时的 FrameDebug 可以发现,每个过程 (如法线 Pass / 深度 Pass/GBufferPass) 都是单独的 Pass, 不过走的是 SrpBatcher
当上述所有 Pass 走完以后,会进入到 DefferedPass 进行最终的渲染

  1. DepthNormal
  2. DepthOnly
  3. RenderGBuffer
  4. DefferedPass

首先,由于 URP 本身通过将渲染分为了不同渲染时机和 RenderFeature, 所以可以很方便把渲染的逻辑拆出来
比如 URP 的 Lit.shader 用 RenderFeature 来划分 GBuffer 还是 Forward 还是 ShadowCaster 还是 DepthOnly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Pass
{
Name "ForwardLit"
Tags
{
"LightMode" = "UniversalForward"
}
}

Pass
{
Name "GBuffer"
Tags{
"LightMode" = "UniversalGBuffer"
}
}

其中顶点 / 片元着色器都被包裹在了 LitGBufferPass.hlsl 脚本中

  1. LitGBufferPassFragment->InitializeStandardLitSurfaceData (input.uv,surfaceData) 是存储表面数据,保存在了 surfaceData

其中 SurfaceData 结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Must match Universal ShaderGraph master node
struct SurfaceData
{
half3 albedo;
half3 specular;
half metallic;
half smoothness;
half3 normalTS;
half3 emission;
half occlusion;
half alpha;
half clearCoatMask;
half clearCoatSmoothness;
};

然后这里 Break 一下,先回到最初的起点,在 FrameDebug 中我们能够明显的看出 Pass 的执行存在顺序关系 (而且这些顺序也不能随便变更,即 DeferedRendering 必须在其他几何 Pass 之后)

那么 URP 本身是在哪里控制这些 Pass 的执行顺序呢?
UniversalRenderer 脚本下的 Setup 函数中我们可以看到如下的几段

  1. Setup 入口处声明了 commandBuffer

  1. 在渲染 UI 前调用 DeferredPass

首先,EnqueueDeferredPass 是在上述所有 NormalsPass 结束后加入 commandBuffer 的,在这个函数中,主要加入了其他几个 Pass

  • GBuffer
  • CopyDepth
  • Deffered
  • ForwardOpaque

所有的 Pass 会被保存到 m_ActiveRenderPassQueue

最后,会经由 UniversalRenderer 的父类 ScriptableRendererExecute 方法将所有对应的 Pass 提交到 CommandBuffer 中
其中 activeRenderPassQueue 等价于 m_ActiveRenderPassQueue 至此,URP 的 Deferred 的渲染从 Shader 到设置到提交的流程就完成了