RenderPassBlockの分類と、FowardRendererの各Passはどのタイミングで実行されるか

※本記事は **Unity2021.1.16f1** を元に記載しています

一つ前の記事

https://qiita.com/ScreenPocket/items/c5e6f5d8959e22b61522

で、
**ScriptableRenderPass.Configure()　は　ScriptableRenderer.InternalStartRendering()　と　ScriptableRenderer.InternalFinishRendering()　の間で、RenderPassBlock分連なっている**
と書いたのですが、では「RenderPassBlockとは何ぞや？」という事も書いておきます

# RenderPassBlockは4つ
連なると書きはしましたが、RenderPassBlockは実は4つしかなく

```cs 
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;
}
```

* 描画前
* 不透明描画
* 半透明描画
* 描画後

の4つだけです。シンプル。
RenderPassをAddする際に指定したRenderPassEventを、この4つの大カテゴリに応じて振り分けて、ブロック毎にExecute()しているわけです。

# RenderPassEventの大別

各RenderPassEventが何処に所属しているかはRenderPassBlockのコードを見ると確認出来ます。

```cs:RenderBlocks.RenderBlocks()の一部を抜粋
m_BlockEventLimits[RenderPassBlock.BeforeRendering] = RenderPassEvent.BeforeRenderingPrePasses;
m_BlockEventLimits[RenderPassBlock.MainRenderingOpaque] = RenderPassEvent.AfterRenderingOpaques;
m_BlockEventLimits[RenderPassBlock.MainRenderingTransparent] = RenderPassEvent.AfterRenderingPostProcessing;
m_BlockEventLimits[RenderPassBlock.AfterRendering] = (RenderPassEvent)Int32.MaxValue;
```

振り分けの条件式を見るに

```cs:RenderBlocks.FillBlockRanges()の一部
while (currRenderPass < activeRenderPassQueue.Count && activeRenderPassQueue[currRenderPass].renderPassEvent < m_BlockEventLimits[i])
    currRenderPass++;
```

「 < m_BlockEventLimits[i]」含まずなので

* RenderPassBlock.BeforeRendering
    * RenderPassEvent.BeforeRendering
    * RenderPassEvent.BeforeRenderingShadows
    * RenderPassEvent.AfterRenderingShadows
* RenderPassBlock.MainRenderingOpaque
    * RenderPassEvent.BeforeRenderingPrePasses
    * RenderPassEvent.AfterRenderingPrePasses
    * RenderPassEvent.BeforeRenderingOpaques
* RenderPassBlock.MainRenderingTransparent
    * RenderPassEvent.AfterRenderingOpaques
    * RenderPassEvent.BeforeRenderingSkybox
    * RenderPassEvent.AfterRenderingSkybox
    * RenderPassEvent.BeforeRenderingTransparents
    * RenderPassEvent.AfterRenderingTransparents
    * RenderPassEvent.BeforeRenderingPostProcessing
* RenderPassBlock.AfterRendering
    * RenderPassEvent.AfterRenderingPostProcessing
    * RenderPassEvent.AfterRendering
    * それ以降

となります。

# ForwardRendererではどうなる？

よって、普通にForwardRendererで描画した場合は、下記のような大別でPassが振り分けられています

* RenderPassBlock.BeforeRendering
    * MainLightShadowCasterPass　←　RenderPassEvent.BeforeRenderingShadows
* RenderPassBlock.MainRenderingOpaque
    * ColorGradingLutPass　←　RenderPassEvent.BeforeRenderingPrePasses
    * DepthOnlyPass　←　RenderPassEvent.BeforeRenderingPrePasses
    * DrawObjectsPass　←　m_RenderOpaqueForwardPassについてはRenderPassEvent.BeforeRenderingOpaques
* RenderPassBlock.MainRenderingTransparent
    * CopyDepthPass　←　RenderPassEvent.AfterRenderingSkybox
    * CopyColorPass　←　RenderPassEvent.AfterRenderingSkybox
    * DrawObjectsPass　←　m_RenderTransparentForwardPassについてはRenderPassEvent.BeforeRenderingTransparents
    * InvokeOnRenderObjectCallbackPass　←　RenderPassEvent.BeforeRenderingPostProcessing
    * PostProcessPass　←　RenderPassEvent.BeforeRenderingPostProcessing　（FinalPostProcessPassはAfterRendering。詳しくはPostProcessingPassesを参照）
* RenderPassBlock.AfterRendering
    * FinalBlitPass　←　RenderPassEvent.AfterRendering + 1
    * SceneViewCopyDepthPass　←　RenderPassEvent.AfterRendering + 9

FrameDebuggerで見た時のお馴染みの順番ですね。
注意点としては↑はあくまで**RenderPassEventを元にリストアップしただけ**なので、 **必ず描画の度に↑のPassが全て実行されるわけではありません**。
PostProcessの有効無効やCameraStackの有無、そしてCameraStackのどの位置のカメラを描画しているか、Depthはクリアするかしないかなどで各Passの有無は変わります。
※FinalBlitPassはCameraStackの最後のカメラのAfterRenderingでしか実行されない、など。

---

ご自身のカスタムPassを、どのタイミングで呼び出したいかの指標になれば幸いです。