simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

Unity:2018のScriptable Render Pipelineに慣れる

Scriptable Render Pipeline(SRP) とは端的に言うと、Unity がフレームをどのようにレンダーするかをデベロッパーが C# で制御できるようにするものです。

ついに Unity のブラックボックスに手を入れられる時代が始まろうとしています。
これを活用できるかどうかがゲーム会社として生きるか死ぬかの分かれ目になりそう。
たくさんの同一オブジェクトをシーンに配置するようなゲームでは特に、パフォーマンスを上げる手段として使えるため
SRPを使えるようになっておかないといけないでしょう。

参考資料は先週開催された cedec 資料のこちらです「Scriptable Render Pipeline を使ってみよう」

www.slideshare.net

まずは今までのブラックボックスレンダリングをホワイトボックスに切り替える具体的な操作から確認します。

参考資料のさらに参考資料として、凹みさんの記事を読みました。
tips.hecomi.com

今ある Forward, Deferred レンダリングでうまくない点
既存の問題点を洗い出して、解決策としてのレンダリングを制御できる API の用意は自然な流れ
それが Scriptable Render Pipeline (SRP) という理解が得られました。

今回試した環境
Unity 2018.2.6f1

では SRP に切り替える方法ですが
Package Manager を起動して SRP 関連をインストールします
Create > Rendering > Lightweight Pipeline Asset
を選択してプロジェクトに SRP オブジェクトを作成

メニューの Edit > Project Settings > Graphics を選択してインスペクタを表示し
f:id:simplestar_tech:20180904215541j:plain
この Scriptable Render Pipeline の項目に、作成した SRP を指定します。

以上

確かに描画が切り替わったようです。
マテリアルが不正な状態となって、Unity特有のどぎついピンク色でべた塗りされてしまいました。
Lightweight Pipeline Asset オブジェクトを選択してインスペクタを確認すると次の通り
うん、解説がないとわからないですね。

f:id:simplestar_tech:20180905065748j:plain

ここでスライド資料にて紹介されていた次の ReadMe をすべて読みました。(SRPのソースコードもここから確認することになります)
github.com

読んでいて、結局こちらも必見でした。(読みました)
blogs.unity3d.com

これらを読んで新しく手に入った知見は
1.シーン内のマテリアルは Lightweight Pipeline 用に作り直す必要があること
2.その新しいマテリアルに作り直す具体的な方法
3.プロジェクト設定はスクリプトから GraphicsSettings.renderPipelineAsset プロパティでアサインできること
でした。(それだけ)

具体的な Lightweight Pipeline の導入手順についてはこちらの方が分かりやすかったです。
tsubakit1.hateblo.jp

では最後に Sample Scenes のリポジトリとして紹介されている次のリンクを確かめます。
github.com
HDRP, LWRP 両方が必要なので、PackageManager から設定しました。
TestbedPipelines フォルダの BasicRenderPipeline シーンから確認してみましょう。

実行するとこんな絵になります。
f:id:simplestar_tech:20180908120059j:plain

シーンのヒエラルキー内のスクリプトコンポーネントはたった一つで以下のコードでした。

using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;

[ExecuteInEditMode]
public class SceneRenderPipeline : MonoBehaviour
{
    public RenderPipelineAsset renderPipelineAsset;

    void OnEnable()
    {
        GraphicsSettings.renderPipelineAsset = renderPipelineAsset;
    }

    void OnValidate()
    {
        GraphicsSettings.renderPipelineAsset = renderPipelineAsset;
    }
}

シーンで設定した RenderPipelineAsset をエディタ変更時またはシーン開始時に GraphicsSettings に設定するだけ
実際に設定したのは BasicRenderPipeline です。
こちらはまさに自作の RenderPipeline で次の実装から作られていました。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.XR;

// Very basic scriptable rendering loop example:
// - Use with BasicRenderPipelineShader.shader (the loop expects "BasicPass" pass type to exist)
// - Supports up to 8 enabled lights in the scene (directional, point or spot)
// - Does the same physically based BRDF as the Standard shader
// - No shadows
// - This loop also does not setup lightmaps, light probes, reflection probes or light cookies

[ExecuteInEditMode]
public class BasicRenderPipeline : RenderPipelineAsset
{
    public bool UseIntermediateRenderTargetBlit;

#if UNITY_EDITOR
    [UnityEditor.MenuItem("Assets/Create/Rendering/Basic Render Pipeline", priority = CoreUtils.assetCreateMenuPriority1)]
    static void CreateBasicRenderPipeline()
    {
        var instance = ScriptableObject.CreateInstance<BasicRenderPipeline>();
        UnityEditor.AssetDatabase.CreateAsset(instance, "Assets/BasicRenderPipelineTutorial/BasicRenderPipeline.asset");
    }

#endif

    protected override IRenderPipeline InternalCreatePipeline()
    {
        return new BasicRenderPipelineInstance(UseIntermediateRenderTargetBlit);
    }
}

public class BasicRenderPipelineInstance : RenderPipeline
{
    bool useIntermediateBlit;

    public BasicRenderPipelineInstance()
    {
        useIntermediateBlit = false;
    }

    public BasicRenderPipelineInstance(bool useIntermediate)
    {
        useIntermediateBlit = useIntermediate;
    }

    public override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
    {
        base.Render(renderContext, cameras);
        BasicRendering.Render(renderContext, cameras, useIntermediateBlit);
    }
}

public static class BasicRendering
{
 ...
}

なるほど、エディターで扱える Asset と実行時に利用する Pipline を合わせて実装する必要があるのですね。
気になる BasicRendering の実装はぜひ最新の次のページをご覧になってください。
github.com

カメラを指定して SkyBox を描くコードを見つけられると思います

// Draw skybox
context.DrawSkybox(camera);

このコードをコメントアウトしてみたところ、すぐに反映されて背景の Skybox の描画が行われなくなりました。

f:id:simplestar_tech:20180908125329j:plain

おおー、今私は Unity の Rendering Pipeline を直接いじれていますよ!
ここを足掛かりに、すこしずつ SRP に慣れていこうと思います。

Unity 最高!