LoginSignup
1
0

VRでスタック可能UIブラーを作ったつもりが、結局行き詰った話(解決済み)

Last updated at Posted at 2023-12-11

丸2日間ずっとやってて、結局解決できないので、どこかに書いて終わりにしようと思いました。
南無。

背景

uGUIを表示したら、後ろをブラーで隠したいじゃないですか。隠したい!
そのまた上にuGUIを置いたら、その裏も隠したい!
VRで!
MetaQuest2, 2022.2, 2023.3, URP, SinglePassInstanced, XRInteractionToolkit

実践

ブラー処理自体はどうやるかというと、
画面をキャプって、そのキャプったテクスチャをぼかして、UI矩形に合わせて表示します。
それ以外知りません。言葉にすると簡単なのですがしぇーだは複雑になります。

ビルトインコンロRPのころはすごい簡単にできました。
GrabPass { }
っていうすごいやつがいて、どこでも画面キャプチャが取れたんです。

それが、URPもといSRPではどうもこいついなくなっちゃったみたいなんですよね・・・?(不安)
ではどうするのか。画面を取る方法は調べたところ、2つある。

1.URPコンフィグにあるOpaqueTextureをチェックつけると使える_CameraOpaqueTextureを使う。

image.png
しかし_CameraOpaqueTextureにはUIは映らない。つまりこういうことです。
不透明オブジェクト描画 > 【ここでキャプチャ】 > 透明オブジェクト描画(UIとか)> ... 
UIが映る前のキャプチャなんです。南無。

2.画面をGrabするカスタムRendererFeatureを実装する。

れんだらふゅーちゃー・・・?ビルトインコンロRPのときに炒めてたCommandBufferという柔軟に描画処理をコントロールできる機能がありました。それのSRP版といったところでしょうか。(違ってたらすみません。)
それを使えば画面をキャプれるそうですが、なんと公式にすごく丁度いいサンプルがありました。嬉しい。
https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@14.0/manual/containers/create-custom-renderer-feature-1.html

長い!後半のVolumeの拡張のところは要りません。
RendererFeatureのことはほとんど知らない状態でしたが、コピーコピーで改造してできた・・・!
output.gif

あれ?
2.gif
VRじゃ映んないんですよね。なぜなんでしょう。諦めてます・・・とほほ。

補足

ところで、スタック可能と言っていますが、ブラーは1つしか使わないなんちゃって仕様になっています。
まず、UI2というレイヤーは標準では描画しないように設定します。
image.png

次に、RenderObjectsというRendererFeaturerでUI2を描画します。ブラーUIがでてくるまでおねんねしてます。
image.png

ランタイムでの流れは、
・画面のキャプチャを取る。
・ブラーUIを表示。
・RenderObjectsをSetActive(true)
・(更に上にスタックする場合)表示されてるUI2オブジェクトをUIレイヤに変更してブラーUIのみ非表示。(キャプチャループするから)
・新しいUI2を表示させる。

こんな感じでがちゃがちゃやっていい感じにできました。ですがVRでできなければ意味がない。もう少し考えたいけどノータイムによりフィニッシュです。薄暗くすっか!

https://github.com/emptybraces/Unity_URP_Stackable_UI_Blur
https://forum.unity.com/threads/blitter-blitcameratexture-seems-to-fail-for-vr-devices-only.1526263/


追記

下記のコードが上手く機能していないようです。

Blitter.BlitCameraTexture(cmd, camera_target_handle, _grabRTHandle, _material, 0);

そこで色々試してみたら、RendererFeatureの実行タイミングがBeforeRenderingSkybox以下であればこのBlit処理が成功しました。はて・・・


追記2

解決しました。RenderTextureの生成オプションにSPI用に追加で設定しないといけなかったみたいです。ランタイム時にSPIかどうか調べる方法が分からなかったのでシンボルで分岐しました。また、MultiPassでは動作していたことを今知った。(MultiPassは現在制作中のプロジェクトでは度外視してて調べても見てなかった。)

#if VR_SPI
	_blurTextureDescriptor.volumeDepth = 2;
	_blurTextureDescriptor.dimension = TextureDimension.Tex2DArray;
#endif

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0