Skip to content

URP ForwardRender

zilch edited this page Feb 9, 2021 · 1 revision

ForwardRenderer 源码分析

ForwardRenderer继承自ScriptableRenderer,ScriptableRenderer的组织结构如下:

  • ScriptableRenderer
    • Block1
      • Pass1
      • Pass2
      • ....
    • Block2
    • ....

Block是根据渲染阶段分的,当前有4个Block:

static class RenderPassBlock
{
    // Executes render passes that are inputs to the main rendering
    // but don't depend on camera state. They all render in monoscopic mode. f.ex, shadow maps.
    public static readonly int BeforeRendering = 0;

    // Main bulk of render pass execution. They required camera state to be properly set
    // and when enabled they will render in stereo.
    public static readonly int MainRenderingOpaque = 1;
    public static readonly int MainRenderingTransparent = 2;

    // Execute after Post-processing.
    public static readonly int AfterRendering = 3;
}

每个Block中,又包含了多个Pass,这些Pass,是通过 ScriptableRenderer.EnqueuePass,加入到管线中的。

那么,接下来我们就要看看,ForwardRenderer往ScriptableRenderer中,到底加入了哪些Pass。

搜索所有调用EnqueuePass的地方,列出几项主要的:

  • EnqueuePass(m_MainLightShadowCasterPass);
  • EnqueuePass(m_AdditionalLightsShadowCasterPass);
  • EnqueuePass(m_DepthPrepass);
  • EnqueuePass(m_ColorGradingLutPass);
  • EnqueuePass(m_RenderOpaqueForwardPass);
  • EnqueuePass(m_DrawSkyboxPass);
  • EnqueuePass(m_CopyDepthPass);
  • EnqueuePass(m_CopyColorPass);
  • EnqueuePass(m_RenderTransparentForwardPass);
  • EnqueuePass(m_OnRenderObjectCallbackPass);
  • EnqueuePass(m_PostProcessPass);
  • EnqueuePass(m_CapturePass);
  • EnqueuePass(m_FinalPostProcessPass);
  • EnqueuePass(m_FinalBlitPass);

这些Pass并不是同时生效的,而是根据管线的配置情况,有条件的组合生效。所有的Pass实现代码位于:Packages/com.unity.render-pipelines.universal/Runtime/Passes

MainLightShadowCasterPass

以主光源的视角,生成一张深度图。用作后续的阴影渲染。

DepthOnlyPass

在URP中,DepthTexture的生成方式有很多种,DepthOnlyPass只是其中之一。

DepthOnlyPass中,摄像机对场景中的物体渲染一遍,生成一张深度贴图。 这并不是一个性能最优的选择。

在条件允许的情况下,URP尽可能不使用这种方式,而是在RenderOpaquePass结束之后,从深度缓存中拷贝出一张深度图(CopyDepthPass)。

ColorGradingLutPass

这个Pass是为相关后处理和HDR预先生成一张颜色查找表。 传送门 - 什么是ColorLut

在URPAsset中的Post-processing配置中,LUT size决定了这张LUT贴图有多大。Unity按照以下规则生成:

width = lutSize*lutSize;
height = lutSize;

即如果lutSize为32,那么lut贴图的大小为1024 * 32.

LUT贴图会在PostProcessPass阶段被用到

DrawObjectsPass

非透明物体和透明物体的渲染,都使用这个类(但是两个实例)。

CopyDepthPass

需要深度贴图,且条件允许的情况下,在非透明物体渲染结束之后,从深度缓存中拷贝信息到_CameraDepthTexture。

这个CopyDepthPass与DepthOnlyPass是互斥的,只要一个开,另一个就会关。

PostProcessPass

图像后处理Pass。 URP中,Unity尽量将所有的后处理使用一个Uber Shader来实现(当然是不可能的,但是尽量)。这有个好处,就是减少的后处理阶段Blit的次数。这里就是一个鱼与熊掌的问题:

  • 如果每个后处理的代码都独立出来,虽然易于扩展维护,但不得不增加Blit次数,牺牲了性能。
  • 如果将后处理代码都合并在一起,虽然耦合高了,但性能友好。