URPでも任意のタイミングでGrabPassする
Built-in Render PipelineからURP(Universal Render Pipeline)でなくなった機能の一つにGrabPassがあります。
フレームバッファをテクスチャに保存し後続のレンダリングパスで参照できる非常に有用な機能だったのですが、Unity的にはパフォーマンスの悪さを気にしているよう[1]でURPではサポートされなくなっています
CameraOpaqueTexture
URPではGrabPassのかわりとしてCameraOpaqueTextureが用意されています。Opaque(不透明オブジェクト)をレンダリングした直後の絵がCameraOpaqueTextureに保存されており後段のレンダリングパスで使用できます
GrabPassの用途としては大抵Transparent(透明オブジェクト)で使用するのでこれで大部分はまかなえるだろうという考えのようです
URPGrabPass
Haruma-Kさんが公開されているURPGrabPassではTransparent後のタイミングでのキャプチャも可能です
もっと細かいタイミングでキャプチャしたい
自分のケースでは
背景オブジェクト描画 → GrabPass → 背景以外の不透明オブジェクト描画 → 透明オブジェクト描画
としたかったので上記の方法では対応できなさそうでした
URPではRenderObjectsRendererFeatureというオブジェクト描画用のRendererFeatureを用意してくれているので、これでOpaqueの内容を分けることにしました
また、単純にキャプチャするだけのRendererFeatureも作成しました
手順
上記GrabColorRendererFeature.cs
をプロジェクトに追加しておきます
キャプチャ対象のオブジェクトを識別するレイヤーを追加し(ここではGrabTarget
としています)、対象オブジェクトのレイヤーをGrabTarget
にしておきます
RendererアセットのInspectorでOpaque Layer MaskからGrabTarget
を除外します。これでURPデフォルトのOpaque描画の対象から外れます
Rendererアセットが行方不明な場合
Edit → ProjectSettings → Graphics → ScriptableRenderPipelineSettingsでレンダーパイプラインアセットを探し、そのInspectorのRenderer Listから見つけることができます
同じくRendererアセットのInspectorからAdd Renderer FeatureボタンでRender Objectsを追加し、次のように設定します
- Event:
BeforeRenderingOpaques
- Filters:
- Queue:
Opaque
- LayerMask:
GrabTarget
- Queue:
同様にGrabColorRendererFeatureも追加、設定します
- RenderPassEvent: 上記RenderObjectsと同じものにする
- Grabbed Texture Name: シェーダーから参照するキャプチャしたテクスチャ名
これでGrabTarget
レイヤーのオブジェクトを先に描画し、その後Opaqueでもキャプチャしたテクスチャを参照できるようになりました
感想
GrabPass的な処理をより細かいタイミングで差し込みたいと調べていくうちに、RenderObjectsRendererFeatureを知ったことであまり特別なコードを書かずともできることがわかりました。GrabPassを差し込むというよりかは、デフォルトの描画を分割していける、といった印象でしょうか。応用すればかなり柔軟に描画処理をカスタイマイズしていけそうですね
参考
Discussion