ホログラム安定化 — MRTK2
パフォーマンス
基盤となる Mixed Reality プラットフォームとデバイスが最適な結果を生むためには、一定のフレーム レートを達成することが重要です。 ターゲット フレーム レート (例: 60 FPS または 90 FPS) は、プラットフォームとデバイスによって異なります。 ただし、フレーム レートを満たしている Mixed Reality アプリケーションは、安定したホログラムを持ち、ヘッド トラッキングやハンド トラッキングなどを効率的に行うことができます。
環境追跡
安定したホログラフィック レンダリングは、プラットフォームとデバイスによる頭部姿勢追跡に大きく依存します。 Unity は、基になるプラットフォームによって推定および提供されるカメラの姿勢から各フレームのシーンをレンダリングします。 この追跡で実際の頭部の動きが正しく追従されない場合、ホログラムの視覚的な表示は不正確になります。 これは、ユーザーが仮想ホログラムを実際の世界に関連付けることができる HoloLens などの AR デバイスでは特に明らかで重要です。 パフォーマンスは、信頼性の高いヘッド トラッキングのために重要ですが、その他にも重要な機能がある場合があります。 ユーザー エクスペリエンスに影響を与える環境要素の種類は、対象となるプラットフォームの特性によって異なります。
Windows Mixed Reality
Windows Mixed Reality プラットフォームには、プラットフォームでのホログラムの安定化に関する参照資料がいくつか用意されています。 ユーザーに対するホログラムの視覚効果を向上させるために開発者が利用できる主要なツールがいくつかあります。
深度バッファーの共有
Unity 開発者は、アプリケーションの深度バッファーをプラットフォームと共有するオプションを使用できます。 これにより、現在のフレームに対してホログラムが存在する場合に、プラットフォームが Late-Stage Reprojection (遅延ステージ再投影) と呼ばれるハードウェア支援型のプロセスを通じて、ホログラムを安定化するために利用できる情報が提供されます。
Late-Stage Reprojection (遅延ステージ再投影)
フレームのレンダリングの最後に、Windows Mixed Reality プラットフォームは、アプリケーションによって生成されたカラーおよび深度レンダー ターゲットを受け取り、最後のヘッド ポーズ予測以降のわずかな頭部の動きを考慮して最終的な画面出力を変換します。 アプリケーションのゲーム ループの実行には時間がかかります。 たとえば、60 FPS の場合、アプリケーションがフレームをレンダリングするのに最長で 16.667 ミリ秒かかることを意味します。 これは非常に短い時間のように思えるかもしれませんが、ユーザーの頭部の位置と向きが変わり、その結果、レンダリング時にカメラの新しい投影マトリックスが生成されます。 遅延ステージ再投影は、この新しいパースペクティブに対応するために最終イメージのピクセルを変換します。
ピクセルごとまたは補正平面の LSR
Windows Mixed Reality デバイスで実行されているデバイスのエンドポイントと OS のバージョンによっては、Late-Stage Reprojection アルゴリズムがピクセルごとに、または補正平面を介して実行されます。
ピクセル単位の深度ベース
ピクセル単位の深度ベースの再投影では、深度バッファーを利用してピクセルあたりのイメージ出力が変更されるため、さまざまな距離でホログラムが安定化されます。 たとえば、1 m 離れた場所にある球体が、10 m 離れた柱の前にあるとします。 ユーザーが頭を少し傾けた場合に、球を表すピクセルは、柱を表す遠く離れたピクセルとは異なる変換になります。 ピクセルごとの再投影では、すべてのピクセルでこの距離の差が考慮され、より正確な再投影が行われます。
安定化平面
プラットフォームと共有するための正確な深度バッファーを作成できない場合、別の形式の LSR では補正平面が使用されます。 シーン内のすべてのホログラムはいくつかの補正を受けますが、目的の平面にあるホログラムは、ハードウェアの最大の補正を受けます。 平面のポイントと法線は、Unity によって提供される HolographicSettings.SetFocusPointForFrame API を介してプラットフォームに提供。
深度バッファーのフォーマット
開発用に HoloLens を対象とする場合は、24 ビットではなく、16 ビット深度バッファー形式を使用することを強くお勧めします。 これにより、パフォーマンスを大幅に節約できますが、深度値の精度が低くなります。 低い精度を補正し、z ファイティングを回避するには、ファー クリップ プレーンを Unity によって設定された 1000 m の既定値から減らすことをお勧めします。
Note
"16 ビットの深度フォーマット" を使用する場合、この設定では Unity はステンシル バッファーを作成しないため、ステンシル バッファーを必要とする効果は機能しません。 "24 ビットの深度の形式" を選択した場合、エンドポイントのグラフィックス プラットフォームが対応する場合は、通常、8 ビットのステンシル バッファーが作成されます。
Unity での深度バッファーの共有
深度ベースの LSR を利用するには、開発者が行う必要がある重要な手順が 2 つあります。
- [編集]>[プロジェクト設定]>[プレーヤー]>[XR 設定]>[Virtual Reality SDK]>[深度バッファー共有] を有効にします。
- HoloLens をターゲットにする場合は、16 ビット深度の形式も選択することをお勧めします。
- 画面に色をレンダリングすると、深度もレンダリングされます
Unity のOpaque GameObjects は、通常、自動的に深度に書き込みます。 ただし、透明なテキスト オブジェクトは、通常、既定では深度に書き込まれません。 MRTK 標準シェーダーまたは Text Mesh Pro を利用している場合は、これを簡単に解決できます。
Note
シーン内のどのオブジェクトが深度バッファーに視覚的に書き込まれないかをすばやく調べるには、MRTK 構成プロファイルの [エディターの設定] の下にある [レンダー深度バッファー] ユーティリティを使用できます。
透明の MRTK 標準シェーダー
MRTK 標準シェーダーを使用した透明な素材の場合は、素材を選択して [インスペクター] ウィンドウで表示します。 次に、[今すぐ修正] ボタンをクリックして、素材を深度に書き込むために変換します (例: Z 書込みオン)。
以前
クリック後
Text Mesh Pro
Text Mesh Pro オブジェクトの場合は、TMP GameObject を選択してインスペクターで表示します。 素材コンポーネントで、割り当てられた素材のシェーダーを MRTK TextMeshPro シェーダーを使用するように切り替えます。
カスタム シェーダー
カスタム シェーダーを作成する場合は、ZWrite フラグを Pass ブロック定義の先頭に追加して、深度バッファーに書き込むようにシェーダーを構成します。
Shader "Custom/MyShader"
{
SubShader
{
Pass
{
...
ZWrite On
...
}
}
}
不透明による支援
上記のメソッドが特定のシナリオ (つまり、Unity UI を使用) で機能しない場合は、別のオブジェクトを用意して深度バッファーに書き込むことができます。 一般的な例としては、シーンのフローティング パネルで Unity UI テキストを使用することが挙げられます。 パネルを不透明にするか、少なくとも深度に書き込むことで、両方のテキストとパネルがプラットフォームによって安定化されます。z 値は互いに非常に近いためです。
WorldAnchors (HoloLens)
視覚的な安定性を確保するために正しい構成が満たされていることを確認すると共に、ホログラムを正しい物理的な場所で安定した状態に保つことが重要です。 開発者は、物理領域内の重要な場所をプラットフォームに通知するために、1 つの場所に留まる必要がある GameObjects の WorldAnchors を活用できます。 WorldAnchor は、そのオブジェクトの変換を完全に制御する、GameObject に追加するコンポーネントです。
HoloLens などのデバイスは、常にスキャンを行い、環境について学習しています。 したがって、HoloLens は空間内の移動と位置を追跡するため、その推定値が更新され、 Unity 座標系が調整されます。 たとえば、GameObject が開始時にカメラから 1 m の場所に置かれていて、HoloLens によって環境が追跡されるときに、GameObject が配置されている物理的な地点が実際には 1.1 m 離れていることが検知される場合があります。 これにより、ホログラムのずれが生成されます。 GameObject に WorldAnchor を適用すると、アンカーはオブジェクトの変換を制御して、オブジェクトが正しい物理的な場所に維持されるようにします (つまり、実行時に 1m ではなく 1.1m 離れた場所に更新します)。 アプリ セッション間で WorldAnchors を維持するために、開発者は WorldAnchorStore を使用して WorldAnchors を保存し、読み込むことができます。
Note
WorldAnchor コンポーネントを GameObject に追加した後は、その GameObject の変換 (つまり、transform.position = x) を変更することはできません。 開発者は、変換を編集するために WorldAnchor を削除する必要があります。
WorldAnchor m_anchor;
public void AddAnchor()
{
this.m_anchor = this.gameObject.AddComponent<WorldAnchor>();
}
public void RemoveAnchor()
{
DestroyImmediate(m_anchor);
}
アンカーを手動で操作する方法については、Microsoft ワールドロック ツールを確認してください。