渋谷ほととぎす通信

Unity・ゲーム開発 技術で一生食べていく情報発信

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

f:id:esakun:20210627191741p:plain

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

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

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

  • 全くSRPを使ったことがないけど興味はある
  • URP、HDRPをそのまま使っていて内部のことは分からない
  • SRPがどういう仕組なのかを少し知りたい

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

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

f:id:esakun:20210717135901p:plain
URPを削除している図

Core RP Libraryのインストール

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

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

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

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

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

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

  • SampleRenderPipeline.cs
  • SampleRenderPipelineAsset.cs

それぞれ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」

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

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

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

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

今回はDrawSkyboxでSkyBoxを描画するコマンドをスケジュールします。
スケジュールしたコマンドをGPUに送るためにsubmitメソッドを呼んでいます。

今回はカメラが1つなのでcameras[0]と雑に処理しています。

SampleRenderPipelineAsset.cs

using UnityEngine;
using UnityEngine.Rendering;

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

SampleRenderPipelineAssetではCreatePipelineメソッドの中で、
先ほどSkyBoxのみを描画する処理を書いた
SampleRenderPipelineインスタンスを返却します。

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

f:id:esakun:20210717162829p:plain

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

f:id:esakun:20210717154959p:plain

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

SRPの適用

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

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

f:id:esakun:20210717163430p:plain

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

完成

f:id:esakun:20210717163549p:plain

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

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

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

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

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

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

f:id:esakun:20210717174645p:plain

ドローコール : 5

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

今回作ったSRPの場合

f:id:esakun:20210717174711p:plain

ドローコール : 1

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

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

まとめ

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

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

f:id:esakun:20210717211034p:plain

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

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

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

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

今回使ったソースコードはコチラにアップしています。

環境

  • Unity2021.1.7f1
  • Core RP Library v10.6.0

参考サイト