Notifications
Article
ScriptableRenderPipelineを自作してみた
Updated a year ago
2.5 K
2
ScriptableRenderPipeline
作成してみたのは こちらのgithubにプロジェクト毎アップしています

作り方について

1.UnityEngine.Experimental.Rendering.RenderPipelineを継承したクラスを定義し、Renderメソッドに描画に関する処理を書いていきます
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Experimental.Rendering; /// RenderPipeline用のアセット [ExecuteInEditMode] public class MyScriptableRenderPipeline : RenderPipelineAsset { protected override IRenderPipeline InternalCreatePipeline() { return new MyScriptableRenderPipelineInstance(); } } /// このプロジェクト向けに作成した ScriptableRenderPipeline( SRP )です public class MyScriptableRenderPipelineInstance : RenderPipeline { /// 描画を行うためのコマンドバッファー private CommandBuffer commandBuffer; /// カリングの結果を格納します private CullResults cullResults; /// カリング用の設定 private ScriptableCullingParameters cullingParams; /// 描画する時のPass名を指定します private ShaderPassName basicPass = new ShaderPassName("BasicPass"); /// <summary> /// 実際の描画処理です。描画の度に呼び出されます /// <param name="context">画面に描画するためのContextオブジェクト</param> /// <param name="cameras">シーン中の有効なカメラ一覧</param> /// </summary> public override void Render(ScriptableRenderContext context, Camera[] cameras) { base.Render(context, cameras); // コマンドバッファーがなければ作成します if (commandBuffer== null) { commandBuffer= new CommandBuffer(); } foreach (var camera in cameras) { // ----- まずは描画用のカリング処理です ----/// // Cameraの情報を元にCulling用のパラメーターを構築します if (!CullResults.GetCullingParameters(camera, out cullingParams)) continue; // Cullingし、描画対象をcullResultsに入れます CullResults.Cull(ref cullingParams, context,ref cullResults); // ---- 画面クリア用の処理です -----// // CommandBufferに積んである描画コマンドをクリアします commandBuffer.Clear(); // 画面をクリアするように、描画コマンドをCommandBufferに積みます commandBuffer.ClearRenderTarget(true, true, Color.black,1.0f); // 描画コマンドを実行します context.ExecuteCommandBuffer(cmd); // ------ ここから下が実際のGameObjectを描画するのに必要な部分です -------// // 描画用の設定を指定します。BasicPassで Opaqueのソートを用いて描画するように設定します var settings = new DrawRendererSettings(camera, basicPass); settings.sorting.flags = SortFlags.CommonOpaque; // 描画の対象を設定します var filterSettings = new FilterRenderersSettings(true) { renderQueueRange = RenderQueueRange.opaque, }; // 設定に合わせて Rendererオブジェクトを描画していきます context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); } } }
2.RendringPipelineに対応したAssetを作成し、GraphicsSettings.renderPipelineAssetにセットします
using UnityEngine; using UnityEditor; using UnityEngine.Rendering; public class MySRPCreate { [MenuItem("Assets/Create/MySRP")] public static void CreateSRP() { var instance = ScriptableObject.CreateInstance<MyScriptableRenderPipeline>(); AssetDatabase.CreateAsset(instance, "Assets/MyScriptableRenderPipeline.asset"); GraphicsSettings.renderPipelineAsset = instance; } }
3. ShaderのLightModeをRenderpipelineに合わせて書き換えます
「ShaderPassName basicPass = new ShaderPassName("BasicPass"); 」の様にPassの名前ベースで描画します
Shader "App/SRP/Shader" { Properties { ...// 色々 } SubShader { Pass { Tags { "LightMode" = "BasicPass"} // <- ShaderPassNameをLightModeでセットします ...// 何か諸々処理とか } } }

・ScriptableRenderPipeline良い点

- 描画順等のRenderingに関する部分に手を入れやすくなりました。 => 従来は各コンポーネントの設定を上手く利用して描画順の制御をしていました。 これには各コンポーネントの特性を熟知している必要がありました。 SRPの登場により、スクリプトでわかりやすく記述することが出来る用になりました。
- 今まで手を入れることが出来なかった細かい部分にも手を入れることが出来る用になりました。  => 影処理の置き換え、描画グループごとのバッチング/インスタンシングの制御、描画順のソートの方法やCullingに関する設定の変更等々出来る用になりました。   ※ Cullingに関する処理を全てオフにすることは出来ません。   これはAnimator等で更新を判断するために利用されているからです。

・ScriptableRenderPipeline導入の際に気を付ける点

- SRPと既存のレンダリングシステムで全く同じShaderは利用できません。 => SRPの対応をするためには、ShaderPassのLightModeを以下のように独自に定義する必要があるためです。 「Tags { "LightMode" = "BasicPass" }」
- Surface Shaderは利用不可能です。 => Shader Graph Toolで作成されたShaderは、Scriptable Render Pipelineを考慮して動作します。
- Cameraのコールバックが効かなくなるため、その内容をSRPで実装しなおす必要があります。 => ImageEffect等を実装しなおしが必要となります。

結論(所感):

 過去の資産との整合性なくなりますので、既存のプロジェクトからの乗り換えは苦労を伴います。  同様にアセットを利用する場合も対応の必要があります。  ただ細かく制御出来るようになりましたので、描画周りをシビアに弄りたいプロジェクトでは導入する価値があります。  クラシックな2Dゲームのようにライト制御やリアルタイムshadowが必要のないゲームでは、比較的シンプルに実装出来ますので導入しやすいかと思います。 もしくは、Unityが提供するHDRP/LWRPの範囲内、もしくはそこから改造して派生していく範囲内で収まるならば導入すると良いでしょう。

YusukeKurokawa (黒河 優介)
Developer Relation Manager/Engineer - Programmer
7
Comments
Developer Relation Manager/Engineer
tamtamビルトインはビルトインで面倒じゃなかったんだなぁ・・・と思う部分もあるが、今後はこっちでアセット(資産)を増やしていかにゃ感
次回の Lightweightから拡張していく話をしようと思うのですが、そっちの方が闇かもですね・・・
0
tamtam
Staff
a year ago
Community Evangelist
ビルトインはビルトインで面倒じゃなかったんだなぁ・・・と思う部分もあるが、今後はこっちでアセット(資産)を増やしていかにゃ感
0