デコシノニッキ

ホロレンジャーの戦いの記録

Reprojectionについて整理する

さらっと更新がかかっていたドキュメント。 描画の安定化周りで、HoloLens 2から微妙に変わっていたので整理します。

docs.microsoft.com

シーンで起こるアニメーションやユーザーが頭を動かす時の動きと視点の変化を考慮し、HoloLens は Reprojection(再投影) と呼ばれる描画を安定化させるテクニックを使っています。

Reprojectionには 4つの方法があります

手法の種類

HoloLens 2 から、 Depth Reprojection という新しいキーワードが登場します。 基本的に、Depth Reprojection を今後使うことが推奨です。

手法 詳細
Depth Reprojection (深度再投影) 最小労力で、最も効果的。レンダリングされるシーンの全ての部分が、ユーザーからの距離に基づいて独立して、 安定化される。深度に急激な変化がある場合、一部のレンダリングアーティファクトが表示される場合がある。このオプションは、HoloLens 2および没入型ヘッドセットでのみ使用できる。
Planar Reprojection (平面再投影) アプリケーション側で安定化を正確に制御できる。平面はアプリケーションによって設定され、その平面上のすべてがシーンの最も安定した部分になります。 ホログラムが平面から離れるほど、安定性が低下する。 このオプションは、すべてのWindows MRプラットフォームで使用できます。
Automatic Planar Reprojection (自動平面再投影) 深度バッファの情報を使用して安定化平面を設定する。このオプションは、HoloLens generation 1およびHoloLens 2で使用できる。
None (何もしない) アプリケーションが何もしない場合、安定化平面をユーザーの視線方向に2メートルに固定して平面再投影が使用される。これは通常、標準以下の結果。

手法の大別

手法を分けると、深度ベースの描画安定化と平面ベースの安定化で分けることができます。

  • 深度ベース: Depth Reprojection
  • 平面ベース: Planar Reprojection、Automatic Planar Reprojection

Automatic Planar Reprojection は一見深度を使っているので深度っぽいがそうではないです。

簡単に言うと、平面上にある部分の描画だけが安定して描画される仕組み。 何もしなければ、基本的に自動的にカメラの常に2m先にこの平面がありますが、見たいオブジェクトや場所がカメラの常に2m先にあるなんて言う話はあり得ないので、アプリケーションからはAPIや設定を通してこの平面の位置を決めてあげる必要があります。

f:id:haikage1755:20191206100845p:plain

Planar Reprojection では奥行をカメラから飛ばしたレイとコライダーの衝突によって得ています。Stabilization Plane Modifier というスクリプトの中身を見ると良く分かります。一方、Automatic Planar Reprojection ではこれを代わりにカメラのDepth 情報から今見ている場所との距離を算出し、それっぽいところに置いてくれているようです。

f:id:haikage1755:20191206101050g:plain

www.tattichan.work

www.tattichan.work

手法の有効化

Windows Mixed Reality SDK (主にUnity2018.4) を使う場合

細かい設定がどうのこうの書いてありますが、今のUnity環境であれば、XR supported にチェックを入れれば自動的に、HoloLens 2 はDepth Reprojection、 HoloLens 1 は Automatic Planar Reprojection になります。

手法 詳細
Depth Reprojection アプリケーションは、レンダリングされたフレームごとに深度バッファーをシステムに送信する。 Unityでは、[Player Settings] の [Enable Depth Buffer Sharing] オプションを有効にすることで使える。SetFocusPointAPIを呼び出してはいけない。
Planar Reprojection (平面再投影) すべてのフレームで、アプリケーションがシステムに安定させる平面の位置を伝える。 Unity では SetFocusPointForFrameを呼び出し、「Enable Depth Buffer Sharing」を無効にする必要がある。
Automatic Planar Reprojection (自動平面再投影) これを有効にするには、アプリケーションはDepth Reprojectionの場合と同様に深度バッファをシステムに送信する必要がある。 HoloLens 2では、アプリケーションはフレームごとに0,0のポイントでSetFocusPointを設定する必要がある。 HoloLens gen 1の場合、アプリケーションはSetFocusPointを呼び出してはいけない。

MRTK 2.2 からは Camera Profile からこの設定を変更することができます。

f:id:haikage1755:20191206101315p:plain

Windows Mixed Reality Plugins (2019.3以降)

補足として、Unity2019.3からは Windows Mixed Reality Plugin を通じてAPIに各種アクセスすることになります。

f:id:haikage1755:20200330024115p:plain:w350

こちらを使う場合、設定の場所が変わるのと設定名がShared Depth Bufferに変更になることに注意してください。

手法の選択

Unity バージョンをあげて、2018.4.13f1にしておくのがいいと思います。

Stabilization Type ImmersiveHeadsets HoloLens gen 1 HoloLens 2
Depth Reprojection 推奨 N/A 推奨 ※Unity 2018.4.12以降またはUnity 2019.3以降を使用する必要あり。それ以外の場合は、Automatic Planar Reprojectionを使用。
Planar Reprojection N/A デフォルト推奨 Depth Reprojection が良くない場合に推奨。 ※Unity 2018.4.12以降またはUnity 2019.3以降を推奨。以前バージョンは、わずかに劣化した再投影結果になる。
Automatic Planar Reprojection 非推奨 Automatic Planar が良くない場合に推奨。 どちらのDepthオプションでも目的の結果が得られない場合。

深度が正しく設定されていることを確認する

Views -> Hologram Stability から現在のアプリケーションがどの手法を用いて安定化をはかっているのかを確認することができます。 f:id:haikage1755:20191206100621p:plain

Show depth or plane in headset. を使用すると、深度や平面が可視化されます。 ※ この設定はMRCでは反映されない

Depth Reprojection が有効な場合

青い部分が深度が適切に設定された部分。赤い部分は、深度が設定されていない部分です。 赤い部分は重い負荷がかかったときなどに、グリッジ(描画の歪み)が発生しやすい部分です。 f:id:haikage1755:20191206100639p:plain:w350

画像を見てわかる通り、Diagonostics (FPSなどを表示しているUI)が真っ赤になっています。UnityではUI系は主に、TextやButtonといったUI系は深度値の書き込みをしていません(基本的にUIは常に手前にくるため)。 また、半透明といったマテリアルの多くも一般的には深度値の書き込みを行っていないため、影響を受ける点であることに気をつけてください。

ホーム画面や3DViewでも、Depth Reprojection が使われていることが分かります。

f:id:haikage1755:20200330025552p:plain:w350

Planar Reprojection と Automatic Planar Reprojection が有効な場合

青い格子平面が、FocusPlaneです。先の説明で使った紫のプレーンは実機上だとこのように見ることができます。
f:id:haikage1755:20191206100651p:plain:w350

Planar Reprojection が使われているのがプリインストールの Hint アプリです。Hintでは、常に対象となるオブジェクトが等距離にあるため Planar Reprojection が有効な手法になります。

f:id:haikage1755:20200330025918p:plain:w350

Unityから深度バッファを確認する

Unityからこの深度値の書き込みを行っているかは簡単にMRTK(2.2以降)を使って簡単に確認することができます。 Render Depth Bufferのボタンを押すと、文字シェーダーなどは深度書き込みを行っていないのでこのように切り替えると真っ白になります。

f:id:haikage1755:20191205233409p:plain:w350

f:id:haikage1755:20191205233221g:plain:w350

Reprojection設定を上書きする(??)

ちなみにこの設定はDevice Portal から上書きすることができるようです。(が、使うのかこれ…)。 試してはみたのですが、Show depth or plane in headset で可視化している様子は切り替わらないので謎です。はい。

f:id:haikage1755:20191206100709p:plain

[デコシノニッキ]は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。」