[Unity] UniversalRenderPipelineについて調べた覚え書き


本記事は、[Craft Egg Advent Calendar 2021](https://qiita.com/advent-calendar/2021/craftegg)の12/2の記事です。

## ◆ 経緯、目的

- 今後モバイル開発では標準となりそうなURP(UniversalRenderPipeline)をあらためて触ろうと思いました。
- セットアップするだけならチュートリアルをさらえば利用は出来ます。
- しかし、カスタマイズ or 独自のRenderPipelineを構築するとなると深い理解が必要と感じたため、
  振り返りつつ実装を追いかける事にしました。

## ◆ 環境

- Unity : 2020.3.22f1
- Universal RP(com.unity.render-pipelines.universal) : 10.7.0
  - 依存パッケージ
    - com.unity.render-pipelines.core : 10.7.0
    - com.unity.shadergraph : 10.7.0
    - com.unity.mathematics : 1.1.0

## ◆ おさらい(既成のものを使うだけでも必要なTIPS)

### □ URPとは？

- [SRP(Scriptable Render Pipeline)](https://docs.unity3d.com/ja/2020.3/Manual/scriptable-render-pipeline-introduction.html) の 一種。Unity2018で登場。
  - 従来のレンダリングパイプラインに差し変わる仕組み。
  - 名前の通り「スクリプタブル」にレンダリングの制御や調整、カスタマイズや構築が行えるようになっている。
- SRPをベースとしたHDRP(High Definition Render Pipeline) と LWRP(Lightweight Definition Render Pipeline)が提供された。
  - HDRP -> コンソールけのハイエンドなレンダリングパイプライン
  - LWRP -> モバイル向けの軽量なレンダリングパイプライン
  - その後、Unity2019の途中でLWRPはURP(Universal Render Pipeline)と改名された。
    - 公式ドキュメント上でもURPが掲載されているのはUnity2019.3～となっている。

### □ URP使用時における Cameraコンポーネントの特徴

- URPを有効にするとCameraコンポーネントの [Inspector表示が差し替わります。](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/manual/camera-component-reference.html)
  - 大項目として Render Type, Projection, Rendering, Environment, Output, Stack のペインに分けられています。
  - 全て書き出すとキリが無いためカテゴリと代表的なものをまとめます。
  - 必ず「Universal Additional Camera Data」コンポーネントが別途Addされた状態になります。

- [Render Type (Base or Overlay)](](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/manual/camera-types-and-render-type.html))
  - Baseカメラのどちらかを重ねて描画することは出来ない。
    - 複数Baseカメラがあった場合は Rendering/Priority によって描画順が決まる。
  - 非SRP構成から移行するのであれば 最奥を描画しているカメラをBaseとするのが一般的と思われる。
    - 透過せず Skybox や 最奥でSolidColorで塗りつぶしているカメラなど。
  - OverlayカメラはただHierarchyに構築するだけでは描画されず、Baseなカメラに対して Stackする必要がある。
    - Camera Stacking と呼ばれる機能。

- Projection
  - 従来のProjection, FOV, Clipping Planes など。

- Rendering
  - 従来の Depth (Priorityに改名), Rendering Path, Culling Mask, Occlusion Culling など。
  - Renderer
    - Render Pipeline Assetに登録されているRendererのうち、どのRendererを使うか選択します。

- Environment
  - 従来の Clear Flags (Background Typeに改名) など。
  - Volumes
    - [Post-processing Volumes](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/manual/Volumes.html)に関する設定。

- Stack ([Camera Stacking](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/manual/camera-stacking.html))
  - Baseカメラに対して重ねるOverlayカメラをリストで持たせる。
  - LWRPリリース当初はこれがなく、複数のカメラで構成されたシーンの移行難度が高かった認識。

- CameraにAddされるコンポーネント : [Universal Additional Camera Data](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/manual/universal-additional-camera-data.html?q=Universal%20Additional%20Camera%20Data)

  - URPにしたことで拡張された、カメラ関連の設定値にアクセスするためのコンポーネント。
  - Inspector上で可視化されているメンバはありません。(InspectorをDebug表示にすれば閲覧可)
  - URPに切り替えると一見、CameraのInspectorが切り替わっているように見えますが、
    Camera定義そのものが置き換わっているわけではないのでこのコンポーネントに値を保持し、
    Inspector上の表示をCameraに統合しているのだと思われます。

## ◆ 関連する定義

### □ 全ての親となる [Render Pipeline Asset](https://docs.unity3d.com/ja/2020.3/ScriptReference/Rendering.RenderPipelineAsset.html)

- 実体は ScriptableObject。
- この ScriptableObject を ProjectSettings/Graphics/Scriptable Render Pipeline Settings に設定すると有効になります。
  - C#コード上からは ```UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset``` で[アクセス可能](https://docs.unity3d.com/ja/2020.3/Manual/srp-setting-render-pipeline-asset.html)です。
- 従来 ProjectSettings/Graphics で行っていた設定の一部がこのアセットに移行しています。
- このアセットに具体的に利用する Renderer(を生成する定義が紐づいたScriptableObject) を設定します。
- URPでは Universal Render Pipeline Asset を使います。

### □ 基底のScriptableRenderer関連

- [ScriptableRendererData](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ScriptableRendererData.html)
  - Render Pipeline Asset に参照させる ScriptableObject。
  - この ScriptableObjectの定義から実際の描画処理が定義される ScriptableRenderer を生成します。
  - Scriptable Renderer と Scriptable Renderer Data は対となります。
    - Scriptable Renderer は Scriptable Renderer Data を渡して生成するのが一般的のようです。
      - 同じ Renderer を利用しつつ、 異なるRenderer Data を渡すといった利用も可能です。
  - 確認環境の URPではデフォルトで以下の2種が利用可能です。
    - ForwardRendererData
    - Renderer2DData
      - 今回の環境では Experimentalでした。一旦置いておきます。
      - 機能名としては 2D Renderer なのですが、定義名は Renderer2D(定義名として数字頭使えないから…)となっています。
  - さらに [ScriptableRendererFeature](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ScriptableRendererFeature.html)という ScriptableObjectを追加する事で既存の描画処理に独自処理を追加することができます。

- [ScriptableRendererFeature](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ScriptableRendererFeature.html)
  - abstract な AddRenderPasses と Create, virtual な Dispose で構成される ScriptableObject。
  - ここで ScriptableRenderPassを生成したり追加したい独自描画処理に渡したい SerializeFieldな情報を持たせる。

- [ScriptableRenderPass](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ScriptableRenderPass.html)
  - 描画単位で分けられた描画処理本体。URPの内部にも様々なScriptableRenderPassが存在する。(以下、その一部を抜粋)
    - PostProcessPass : PostProcessingに関連した描画処理。
    - DrawSkyboxPass : Skyboxに関連した描画処理。
    - DrawObjectsPass : 各Objectに関連した描画処理。
  - 独自の描画処理を追加する場合は ScriptableRendererFeatureと合わせて定義を構築し、RendererDataのFeaturesに参照させる。

- [ScriptableRenderer](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ScriptableRenderer.html)
  - ScriptableRendererData.Create() 経由で生成される描画処理本体。
  - IDisposableなクラス定義となっている。
  - Profiling、Profiling.RenderBlock、Profiling.RenderPass、RenderingFeatures、RenderPassBlock、RenderBlocksなどといった定義を持つ。
  - 各種定義(RendererFeature,RenderPass)から
    プロファイリングをしながら CommandBufferを生成して実行しています。

### □ [ForwardRenderer](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ForwardRenderer.html)

- URPの実質デフォルトのScriptableRenderer。(2DRendererのExperimentalが外れたなら応じて棲み分けされそう)
- URPを使うにあたって標準でサポートされる ScriptableRenderPassを持っている。(以下、抜粋)
  - ColorGradingLutPass
  - DepthOnlyPass
  - DepthNormalOnlyPass
  - MainLightShadowCasterPass
  - AdditionalLightsShadowCasterPass
  - GBufferPass
  - CopyDepthPass
  - TileDepthRangePass
  - DeferredPass
  - DrawObjectsPass
  - DrawSkyboxPass
  - CopyColorPass
  - TransparentSettingsPass
  - InvokeOnRenderObjectCallbackPass
  - PostProcessPass
  - FinalBlitPass
  - CapturePass
  - XROcclusionMeshPass
  - SceneViewDepthCopyPass

- [ForwardRendererData](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ForwardRendererData.html)
  - 各Passで用いるシェーダーを参照している ShaderResources や PostProcessData を参照しています。
  - [ForwardRendererData.ShaderResources](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.ForwardRendererData.ShaderResources.html)
    - エディタ実行時には各シェーダーがnullになっていないかリロードを試行しているようです。
      - シェーダー本体はURPパッケージ内のShadersに展開されています。

### □ [PostProcessing](https://docs.unity3d.com/ja/2020.3/Manual/PostProcessingOverview.html)

- [PostProcessData](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.PostProcessData.html)
  - 画面効果に関するシェーダーやテクスチャなどを保持しています。
  - [PostProcessData.ShaderResources](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.PostProcessData.ShaderResources.html)
  - [PostProcessData.TextureResources](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.7/api/UnityEngine.Rendering.Universal.PostProcessData.TextureResources.html)

## ◆ 実際に触ってみた

- 検証には ユニティちゃんSunny Side Up、キャラクター立ち絵パック (© UTJ/UCL) を利用しております。

### □ RendererFeature の追加

- RendererFeature追加前
![URP_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/dd749650-f864-523c-374d-b3d17682ca52.png)

- RendererFeature追加後
![URP_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/0ab5b7fb-0848-1ff1-5401-c1f96fc9ec7c.png)

- 実際に画面に反映されるところまで構築できたため、ここから色々と試行していけたらと思います。

明日は@Tomy_0331の記事です！