こんにちは、Unityエンジニアのオオバです。

SRPとはScriptableRenderPipelineの略で(以下:SRP)、
今までUnity内で閉じていた描画フローを
C#から操作できるようにした機能です。

今回は「初めてのSRP」ということで、
最小コードでカスタムレンダーパイプラインを作ってみて、
SRPのことを理解していこうと思います。

こんな方々に読んでいただければと思います

👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

【準備】すでにURP・HDRPがインストールされている場合は削除

今回はイチからレンダリングパイプラインを作成するため、
URP・HDRPは削除しておきます。

URPを削除している図

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_0

Core RP Libraryのインストール

イチからカスタムレンダーパイプラインを作るときは、
Core RP Libraryを使うと良いと公式ドキュメントに紹介されています

"com.unity.render-pipelines.core": "10.6.0"  

manifest.jsonに👆の一行を追加します。
今回はv10.6.0を使用します。

SkyBoxを表示するだけのレンダリングパイプラインの作成

今回は初めてのカスタムレンダリングパイプラインなので、
シンプルな題材としてSkyboxを表示するだけのパイプラインを作っていきます。

最初に2つのC#ファイルを作成します。

それぞれRenderPipelineRenderPipelineAssetクラスを継承します。

💻ソースコード : SampleRenderPipeline.cs
using UnityEngine;  
using UnityEngine.Rendering;  

public class SampleRenderPipeline : RenderPipeline  
{
    protected override void Render(ScriptableRenderContext context, Camera[] cameras)  
    {
        // Skyboxを描画する  
        context.DrawSkybox(cameras[0]);  
        context.Submit();  
    }
}

Renderメソッドはレンダリングのエントリーポイントで、
この中に描画コマンドのスケジューリング、実行処理を書いていきます。

重要人物「ScriptableRenderContext」

ScriptableRenderContext
C#でUnityの低レベルグラフィックコードを実行するインターフェースとして機能します。

さまざまな描画コマンドメソッドが定義されています。

// Skyboxを描画するコマンドのスケジュール  
context.DrawSkybox(cameras[0]);  

// スケジュールしたコマンドの実行を依頼  
context.Submit();  

DrawSkyboxでSkyBoxを
描画するコマンドをスケジュールしています。

submitメソッドでスケジュールした
コマンドをGPUに送ります。

💻ソースコード : SampleRenderPipelineAsset.cs
using UnityEngine;  
using UnityEngine.Rendering;  

[CreateAssetMenu]  
public class SampleRenderPipelineAsset : RenderPipelineAsset  
{
    ///  
    /// 最初のフレームを描画する前に呼ばれるメソッド  
    /// RenderPipelineAssetの設定が変更されるとRenderPipelineインスタンスを破棄して、  
    /// 次のフレーム描画前に呼ばれる  
    ///  
    protected override RenderPipeline CreatePipeline()  
    {
        return new SampleRenderPipeline();  
    }
}

SampleRenderPipelineAsset
CreatePipelineメソッドの中で、
SampleRenderPipelineインスタンスを返却します。

先ほどSkyBoxのみを描画する処理を書いた

CreatePipelineメソッドは描画される前に実行され、
RenderPipelineAssetの設定が変更されるとインスタンスは破棄。
次のフレーム描画前に再度呼ばれます。

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_1

SampleRenderPipelineAssetScriptableObject
Create > SampleRenderPipelineAsset
コンテキストメニューから作成します。

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_2

Project構成はこんな感じです。

SRPの適用

何もしなければビルトインレンダーパイプラインが適用されます。
今回作ったカスタムレンダーパイプラインの適用方法の紹介をしていきます。

Edit > ProjectSettings > Graphics > Scriptable Render Pipeline SettingsからSRPの設定をしていきます。

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_3

👆の通り先ほど作成したSampleRenderPipelineAssetをセットします。
これでSRPが適用されました。

完成

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_4

SkyBoxが表示するだけのレンダリングパイプラインの完成です。

パッと見なにも起きていないように見えますが、SRPが適用されています。

フレームデバッガでSRPの確認

本当にSRPが適用されているのかフレームデバッガで確認してみます。
Window > Analysis > Frame Debuggerからフレームデバッガを表示します。

フレームデバッガとは1フレーム内の描画処理全て確認できるデバッグ機能です。
描画の負荷や不具合の調査に使ったりします。

ビルトインレンダリングパイプラインの場合

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_5

ドローコール : 5

何もしてなさそうなシーンでも色々と処理をしているんですね。

今回作ったSRPの場合

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_6

ドローコール : 1

Skyboxを描画のみ!!
これでSRPが適用されていることが分かります。

自分が本当に必要としている機能だけを描画する事ができるため使いこなすことができれば不要な処理を省いたパフォーマンスの高い描画が実現できそうですね。

まとめ

初めてのScriptable Render Pipelineでカスタムなレンダーパイプラインを作ってみました。

Skyboxを描画するだけというシンプルな処理でしたが、
SRPの概要は理解できたのではないでしょうか。

【初めてのSRP】Skyboxを描画するだけのカスタムレンダーパイプラインを作って理解を深めよう!_7

図にするとこのようなイメージです。
カスタムしたレンダーパイプラインを、
Unityのレンダーパイプラインにセットして適用します。

必要な処理のみが実行される

フレームデバッガで確認すると、
カスタムレンダーパイプライン内の処理のみが計上されていることが分かりました。
必要なものだけを選択した描画処理を作ることも可能になりそうです。

本記事が理解を深めて行く手前の手助けになればと思います。

GitHub - baobao/SimpleSRP-DrawSkybox: This project is a sample of how to start a custom render pipeline using SRP.
今回使ったソースコードはコチラにアップしています。

参考サイト

オススメ記事
検証環境