ShaderTips

シェーダーTips

主にUnityシェーダーについての記事を書いています。

【Unity】SRP (Scriptable Render Pipeline) 入門①

SRPとは?

Unityではプログラマが作業をしなくてもレンダリングしてくれますが、既存の描画フローを変更することができません。 細かい部分まで突き詰めようとすると、Unity既存の描画フローを使わずに自作したくなります。 それを可能とするのがSRP(Scriptable Render Pipeline)です。

SRPは、レンダーパイプラインの各機能をモジュール単位で分割し、それぞれをC#経由で呼び出せるようにしました。ユーザーはそれぞれの機能を呼び出すC#コードを記述することで、任意のレンダーパイプラインを実装できます。

とはいえ、SRPを使ってゼロからレンダーパイプラインを実装するのは膨大なコストがかかります。 UnityではSRPをベースに実装したURP(Universal Render Pipeline)とHDRP(High Definition Render Pipeline)が用意されています。

URP(Universal Render Pipeline)

モバイルゲームからハイエンドコンソールゲームまでを対象にした、汎用的に利用可能なパイプラインです。様々なプラットフォームで、汎用的に利用可能なものとして、開発されており、従来のレンダーパイプラインよりも、クオリティが向上し、軽量化もされています。 将来的には既存のレンダーパイプラインから代替される予定です。

HDRP(High Definition Render Pipeline)

コンシューマ機やPCなど、ハイエンド環境での利用を想定していて、コン ピュートシェーダーを用いた高度な演算により、高い精度と表現力を持つ描画を実現します。

画面を塗りつぶすだけのSRP

PackageManagerからCore RP Libraryをインストールしておいてください。 f:id:Ny_Program:20210613171622p:plain

手順

  1. RenderPipelineとRenderPipelineAssetを継承した独自クラスを実装します。

  2. RenderPipelineAssetを軽装したクラスのAssetを作成し、GraphicsSetting.renderPipelineAssetにセットする。

RenderPipeline

Experimental.Rendering.RenderPipeline - Unity スクリプトリファレンス

abstractクラスでRender関数をoverrideする必要があります。 この関数内で描画処理を行います。

protected abstract void Render(ScriptableRenderContext context, Camera[] cameras);
RenderPipelineAsset

Rendering.RenderPipelineAsset - Unity スクリプトリファレンス

ScriptableObjectを継承しているので、ScriptableObject化してアセットとして保存できるようになっています。 また、RenderPipelineで使用する設定値などを保持しておくこともできます。 abstractクラスでCreatePipeliner関数をoverrideする必要があります。

protected abstract RenderPipeline CreatePipeline();

今回実装したコードはこちらにです。

using UnityEngine;
using UnityEngine.Rendering;
// 忘れないように
using UnityEngine.Experimental.Rendering;

// スクリプトを Edit モードで実行
[ExecuteInEditMode]
// RenderPipelineAssetを継承
public class BasicAssetPipe : RenderPipelineAsset
{
    public Color clearColor = Color.green;

    protected override RenderPipeline CreatePipeline()
    {
       return new BasicPipeInstance(clearColor);
    }

    #if UNITY_EDITOR
    [UnityEditor.MenuItem("SRP-Demo/01 - Create Basic Asset Pipeline")]
    static void CraeteBasicAssetPipeline()
    {
        // このクラスのインスタンスを作成
        var instance = ScriptableObject.CreateInstance<BasicAssetPipe>();
        // アセット化
        UnityEditor.AssetDatabase.CreateAsset(instance, "Assets/Shader/SRP/1-BasicAssetPipe.asset");
    }
#endif
}

// RenderPipelineを継承
public class BasicPipeInstance : RenderPipeline
{
    private Color m_ClearColor = Color.black;

    public BasicPipeInstance(Color clearColor)
    {
        m_ClearColor = clearColor;
    }

    /// <summary>
    /// 描画処理
    /// </summary>
    protected override void Render(ScriptableRenderContext context, Camera[] cameras)
    {
        var cmd = new CommandBuffer();
        // レンダーターゲットを設定した色で塗りつぶす
        cmd.ClearRenderTarget(true, true, m_ClearColor);
        // コマンドバッファを即時実行
        context.ExecuteCommandBuffer(cmd);
        cmd.Release();
        // スケジュールされたすべてのコマンドをレンダリングループに送信して実行します。
        context.Submit();
    }
}
    [UnityEditor.MenuItem("SRP-Demo/01 - Create Basic Asset Pipeline")]
    static void CraeteBasicAssetPipeline()
    {
        // このクラスのインスタンスを作成
        var instance = ScriptableObject.CreateInstance<BasicAssetPipe>();
        // アセット化(引数は任意のpathを指定してください)
        UnityEditor.AssetDatabase.CreateAsset(instance, "Assets/Shader/SRP/1-BasicAssetPipe.asset");
    }

実装したSRPを適用

UnityEditor.MenuItemを使うと下の画像のようにメニューからこの関数を呼び出せるようになります。 f:id:Ny_Program:20210613172812p:plain

01 - Create Basic Asset Pipelineを押下すると BasicAssetPipeがAsset化されます。 f:id:Ny_Program:20210613175706p:plain

Edit>ProjectSettings>GraphicsSettingsを開きます。 Scriptable Render Pipeline Settingsの項目にBasicAssetPipeをドラッグ&ドロップすることで実装したSRPが有効になります。 f:id:Ny_Program:20210613175800p:plain

    public Color clearColor = Color.green;
    protected override RenderPipeline CreatePipeline()
    {
       return new BasicPipeInstance(clearColor);
    }

変数clearColorの値はBasicAssetPipeのInspectorから設定できます。 BasicPipeInstancを生成しつつ、ClearColorを渡しています。 f:id:Ny_Program:20210613181206p:plain

   protected override void Render(ScriptableRenderContext context, Camera[] cameras)
    {
        var cmd = new CommandBuffer();
        // レンダーターゲットを設定した色で塗りつぶす
        cmd.ClearRenderTarget(true, true, m_ClearColor);
        // コマンドバッファを即時実行
        context.ExecuteCommandBuffer(cmd);
        cmd.Release();
        // スケジュールされたすべてのコマンドをレンダリングループに送信して実行します。
        context.Submit();
    }

Render関数では描画をするためのコマンド等を持つScriptableRenderContextとシーンに配置されているCameraの配列が渡されます。 今回はコマンドバッファーを使ってレンダーターゲットをBasicAssetPipeから受け取った色で上書きします。

描画結果はこんな感じです。 f:id:Ny_Program:20210613183933p:plain

次回は不透明オブジェクトと半透明オブジェクトの描画を行います。

ny-program.hatenablog.com

参考

Scriptable Render Pipeline(SRP)についてちょっと調べてみた - e.blog

↑SRPの実装が少し古いので注意

【Unity】SRPを自作して独自の描画フローを構築する - Qiita Scriptable Render Pipelineを使ってみよう | Unity Learning Materials