Asynchronous TimewarpやAsynchronous SpacewarpなどのOculusの神技術を整理する

Oculusが開発したAsynchronous TimewarpAsynchronous Spacewarp、それにまつわる周辺技術や変遷を比較した記事があったのでまとめます。

OculusはAsynchronous TimewarpAsynchronous SpacewarpといったHMDへの描画技術開発において常にトップを走り続けてきました。SteamVRなどのプラットフォームも後追いでこれらの技術レベルに追いつこうとしていますが、完成度が低かったり、そもそも機能が無かったりします。つまり今も独走状態です。

以下の記事は、そんなOculusの技術について全体を振り返りつつ、開発者がやるべき事を整理したDeveloper Guide to ASW 2.0の翻訳記事になります。


昨年4月、ASW 1.0のパワーとPositional Timewarp (PTW)を組み合わせ、高品質で低レイテンシのVRを提供するAsynchronous Spacewarp(ASW)2.0のリリースを発表しました。

このブログエントリでは、最初のASW 2.0の投稿日本語訳)に基づいて、より技術的な詳細と、VRアプリケーションがASW 2.0に対応していることを確認するためのヒントを提供します。

この記事の技術的な性質を考慮して、Oculusや記事全体を通して議論されているVR固有の用語について、この記事の最後にある用語集を参照してください。

PTWへの道

2016年、非同期タイムワープ(ATW)させることができたら、その次にPTWをリリースすることは理にかなっているように見えるかもしれませんが、その時は別の解決策もあり得ました。もちろんその機能はASWであり、ASWはアニメーションやHMDトラッキング(HMD変換を含む)などのさまざまなモーションキューを時間的に平滑化できますが、PTWはHMDトラッキングに対してだけ一時的に修正できます。その意味では、ASWはPTWを含んだ上位機能のように見えますが、PTWにはASWが完全に対処しなかった独自の利点があることもすぐにわかります。

2017年には、Oculus Dashとともに、VRアプリが深度バッファーを(Oculusランタイムに)送信する際に、ovrLayerEyeFovDepthと呼ばれる新しいレイヤータイプを使用した深度合成を支援するオプションを導入しました。 下のスクリーンショットに見られるように、深度バッファーは、VRアプリのコンテンツがOculus Dashのコンテンツに混ざり合うときに、X線効果を適用するために使用されます。 同時に、エンジン統合チームは、Unreal Engine 4およびUnityでこのレイヤータイプを利用出来るようにし始めました。

ほとんどのVRアプリは、HMDのネイティブリフレッシュレートで実行するように最適化されており、単独でのみ動作します。 これにより、Oculus Dashが表示され、CPUまたはGPUがパフォーマンスの予算を超えたときに、アプリのフレームがドロップを引き起こす可能性があります。
これらの場合、Oculusランタイムは、VRアプリにASWを自動的に適用します。 ただし、ASWは常に1つのcompositor layerだけに制限されているため、Oculus DashとVRアプリが同時にそのフレームレートで実行できない場合、ASWに頼らずにOculus Dashコンテンツの動きをスムーズにする方法も必要です。 これが、PTWを使用する意味があったポイントです。 Oculus Dash向けにPTWを洗練させたので、PTWでうまく動作するようにASWを更新し、時間的安定性をさらに向上させました。このようにしてASW 2.0は生まれたのです。

ASW 1.0 vs 2.0

以下は、ロボリコールで動作しているASW 1.0と2.0を比較したビデオです。 白い矢印は、ASWによるコンテンツの動きをワープ処理する際に使用される、タイルごとに計算された動きベクトルを示すデバッグ表示です。

以下の静止画は、主な違いを説明するのに役立ちます。 ASW 1.0では、掲示板の視差(頭部の動きによる)がどのようにASWによってのみ補正されているかに注目してください。 PTWを使用しするようになったASW 2.0では、PTWが主に対処しているため、同じ視差が最小限のASW補正を登録しています。 予想通り、回転するファンブレードは依然としてASWによって補正されていますが、椅子およびジオメトリの端のわずかな補正は、PTWが働く後のASWの動きベクトルによって捕捉される、遮蔽の解消や視界に依存するシェーディングに起因しています。

ASWとPTWの組み合わせる

ASWがPTWでどのように機能するかをよりよく理解するには、最初にASWのフローを見ていく必要があります。 OculusランタイムがASWを利用するために実行する手順の概要を以下に示します。

  1. ASW は、フォーカス中のVRアプリによって送信された、直前および現在のovrLayerEyeFovフレームのテクスチャをキャプチャします。
  2. ASW は、前のフレームをタイムワーピングして現在のフレームのポーズを使用することにより、「pre-warp frame」を生成します。
  3. ASW は、現在およびpre-warp frameのテクスチャをGPUビデオエンコーダーフレンドリーなリソースに変換します。
  4. ASW は、コレスポンデンス分析のために両方のフレームテクスチャをGPUビデオエンコーダーに送信します。
  5. ASW は、GPUビデオエンコーダー出力から「動きベクトル」を収集します。
  6. ASW は、フレーム補完のために動きベクトルを後処理および変換します。
  7. ASW は、コンテンツをパッケージ化し、VRアプリから来たかのようにcompositor layerに注入します。
  8. Compositor は、ASWが注入したovrLayerEyeFovレイヤーのコンテンツを使用して、普段通りタイムワープおよび(レンズ)ディストーション処理を行います。

手順#2と#8でわかるように、私たちの仕組みはTimewarp(TW)の上に成り立っています。 ASWの元の実装では、PTWに使用する深度バッファがないため、これらの場合に使用されるTWのリプロジェクション手法はOrientation Timewarp(OTW)でした。ただし、より多くのVRアプリが深度バッファーを提供し始めているため、PTWのデータを活用できます。トリックは、上記の両方のステップで使用されるTWのリプロジェクション手法(OTWまたはPTW)が同じ種類であることを確認することです。これにより、ASWまたはTWでHMDの動きのリプロジェクションが確実に修正されますが、視覚的なゴミがでる可能性があるため、一度に両方の場所で修正されません。深度情報が利用できない場合(つまり、VRアプリがovrLayerEyeFovDepthの代わりにovrLayerEyeFovを送信する場合)、Oculusランタイムは、自動的にそのVRアプリをASW 1.0の手法に戻します。

PTWの味

PTWはさまざまな方法で実装できます。VR特有の性質にまつわる要件には、考慮すべき2つの非常に重要なポイントがあります。

PTWにはできるだけ少ないGPUサイクルを使用して、VRアプリがGPUの使用を最大化できるようにします。
各新しいVRアプリのレンダーは、前のものに非常に近い新しいHMDの姿勢を使用するため、最後のビュー位置からの大幅なリプロジェクション誤差に対処する必要はありません。
PTWから得られる各リプロジェクションの結果は、VRアプリによって非常に高いレートで新しい画像が提供されるため、一瞬(通常20ミリ秒未満)しか表示されません。
リアルタイムグラフィックスの文献に精通している人は、視差マッピング、視差オクルージョンマッピング(レリーフマッピングとも呼ばれます)、レイ/球体/コーンマーチングを使用した亜種、高さマップラスタライズなどの類似のテクニックを知っています。これらの手法のほとんどでは、シェーダーはハイトマップテクスチャをサンプリングして、テクスチャサンプルのルックアップをどの程度オフセットするかを認識します。 PTWで使用される深度バッファは、カメラに面するように回転したハイトマップと考えることもできます。

長年にわたり、我々はさまざまなトレードオフを評価するため、多くの違った手法をPTWに試しました。視差オクルージョンマッピングなどの手法の一部は、GPUサイクルのコストが高くなる一方で、より正確になります。ここで決めた手法は、上記のすべての点を認識するのに役立つため、疎視差マッピング手法に似ています。 OTWと比較して、我々の手法をしようするPTWのオーバーヘッドは非常に低く、HMDの移動によりOTWで見られるカクつきに対処するのには十分です。ほとんどの場合、PTW対OTWを使用した場合のGPUパフォーマンス低下は、フレームタイミングのバラツキに紛れて分からないほどです。

「深さ」について深掘りする

PTWは主に深度バッファーの上に成り立っています。深度バッファーについてはオンラインの至る所に情報がありますが、もう少し詳しく見てみましょう。深度バッファはリアルタイムレンダリングで重要な役割を果たし、その内部表現はGPUパフォーマンスの最適化と連動して時間とともにより複雑になりました。ただし、そのコアでは、深度バッファーは、バッファー内のすべての要素が対応する、カラーバッファー要素の深度値を格納する3Dシーンを、ラスタライズするときにGPUによって生成される値の2D配列です。深度バッファーは通常、オクルージョンカリングのためにGPUで使用されるラスター化の副産物として生成されるため、生成のコストは主に考慮されます。 PTWの場合、VRアプリのレンダリング中に深度バッファーが生成されると、VRアプリはovrLayerEyeFovDepthレイヤーの一部としてそのコンテンツを送信することが期待されます。その時点から、Oculusランタイムのcompositorは、Timewarpと(レンズ)ディストーションの処理ステージで、PTWの残りのリプロジェクション処理を行います。

深度バッファーは、浮動小数点形式または正規化整数形式の値を保持できますが、これらの未加工の値は、特定のピクセルの距離を直接表すものではありません。 代わりに、深度値は、各頂点、および順番にピクセルをメモリに格納される最終深度値に変換する投影行列を使用して、ラスタライズ中に計算されます。 投影行列が線形距離を値に変換する方法は、深度バッファーにすぐに格納できるため、線形な距離の値を効率的にマッピングし、視点に近い要素の精度を高める方法として考えることができます。

異なるコンテンツは、異なるマッピングスキームとクリッピング境界を呼び出すことができます。 たとえば、以前の低精度の整数ベースの深度フォーマットでは、カメラのフラストラム(錐台)のニアクリッピング面とファークリッピング面の距離がフラストレーションの大きな原因でしたが、最近では浮動小数点値、投影行列 ファークリッププレーンを無限にマッピングできます。 最終的な深度値への線形距離のマッピングは、浮動小数点形式に組み込まれた精度が便利な場合に役立ちます。 特定の頂点が三角形に変換され、ラスタライズされると、投影範囲とフラストラムの外側の要素がGPUによって自動的に切り取られることに注意してください。

これらすべての考慮すべき事項のために、我々は射影行列を作成する一般的な手法を表す列挙子とともに、アプリ開発者が射影行列を作成するときに使用するヘルパー関数をOculus Rift PC SDKに作成しました。 SDKにあるOVR_CAPI_Util.hファイルからの抜粋を次に示します。これは、射影行列を指定するために提供されるモディファイヤを示しています。 各列挙子の説明については、PC SDKのドキュメントを参照してください。

enum ovrProjectionModifier {
  ovrProjection_LeftHanded,
  ovrProjection_FarLessThanNear,
  ovrProjection_FarClipAtInfinity,
  ovrProjection_ClipRangeOpenGL
};

PTWの場合、トラッキング空間単位で3Dレンダーのカメラまでの各ピクセルの距離に関心があります。 VRアプリが深度バッファーのみを送信し、追加のメタデータは送信しない場合、Oculusランタイムには、ピクセルの元の線形距離を再計算するのに十分な情報がありません。これで、VRアプリで使用される射影行列がPTWアルゴリズムで必要な情報の一部であることは明らかです。ただし、PTWはマトリックス全体を必要としません。レンダリングされた要素のZおよびW座標に関係する部分のみを必要とします。射影行列から必要なコンポーネントを抽出するために、SDKは ovrTimewarpProjectionDesc と呼ばれる最小量の情報と ovrTimewarpProjectionDesc_FromProjection と呼ばれるこれを行うヘルパー関数をきちんとパックする構造も提供します。 VRアプリ開発者が独自の行列形式をSDK形式に変換したくない場合は、関数の実装を確認し、必要なコンポーネントを簡単に抽出できます。

必要とされるもう1つのデータは、おそらくそれほど明白ではありませんが、VRアプリがレンダリングユニットに使用しているワールドとビューのスケールです。 一部のレンダリングエンジンでは、ワールドユニットのスケール変換は射影行列の一部として処理されないため、特別な注意が必要です。 Oculus Rift PC SDKの追跡値は常にメートルの単位で処理される(つまり、1単位は1メートルです)ので、1単位1センチメートルのゲームエンジンを考えてみます。 上記のエンジンが4メートル離れた平面をレンダリングする場合、深度バッファーに適用される投影行列の逆数は400単位の距離を生成します。 ただし、PTWアルゴリズムでは、4単位を計算することが本当に必要です。 したがって、この例では、このスケールの係数が射影行列で既にキャプチャされていない限り、0.01のレンダリングスケール係数がOculusランタイムに提供されます。 VRアプリは、ovrViewScaleDesc 構造体を使用してこの値をSDKに個別に送信できます。

既知のAPIの制限

現在の深度送信APIにはいくつかの制限があります。 いくつか例を挙げると:

  • FovDepthレイヤーで送信される深度バッファーとカラーバッファーは、一致する解像度を使用する必要があります。
  • OVR_FORMAT_R32_FLOATなどの深度バッファーの「カラー」フォーマットはサポートしていません。
  • 現在、マルチサンプリング(つまりMSAA)なしのOVR_FORMAT_D32_FLOATが最適な方法です。 他の形式は、OculusランタイムでリソースのコピーまたはMSAAのリゾルブ処理を引き起こす可能性があります。

まとめと最終的な考え

VRアプリでPTWを活用するために、Oculus Rift PCランタイムはアプリ開発者が次の様なことを求めています。

  • 深度バッファーをovrLayerEyeFovDepthレイヤーの DepthTexture スワップチェーンにラスタライズまたはコピーします。
  • レイヤーの ProjectionDesc データメンバーの射影行列パラメーターを(Oculusランタイム)に提供します。
  • レイヤーを送信するときに、ovrViewScaleDesc 構造体を使用して HmdSpaceToWorldScaleInMeters パラメーターを提供します。
    Unreal Engine 4 または Unity をあなたが使っている場合、最新のOculusエンジン統合により、深度バッファーをOculus Rift PCランタイムに送信するために必要な機能が既に提供されていることに留意してください。

深度バッファを送信するために必要な手順を示すために既に更新されている OculusRoomTiny および OculusWorldDemo サンプルを見ても良いでしょう。
OculusWorldDemoは、PTWがどのように役立つかを確認するための追加のツールもメニューに用意されています(「Tab」キーで切り替えます)。TimeWarpメニューに移動し、フレーム時間を増やしてフレームレートを下げ、[レイヤー]→[メインレイヤー]オプションで、深度送信のオン/オフを切り替えます。

いつものように、何か問題にぶつかったり、質問があったら、私たちのフォーラムに気軽に連絡してください。ハッピーコーディング!

  • Volga Aksoy + Dean Beeler

用語集

VRアプリ:レンダリングされたコンテンツをOculus Riftランタイムにサブミットするソフトウェアアプリケーション。これはVR Compositorを通じて、最終的にOculus Rift HMDに表示されます。

TW(Timewarp)

Oculus RiftランタイムにあるOculus VR Compositorの機能。VRアプリでレンダリングされたコンテンツを最新のHMDトラッキング読み取り値で再投影(リプロジェクション)することで、レイテンシーを削減します。

OTW(Orientation Timewarp)

3DoF TWとも呼ばれる、HMDの回転(方向/姿勢の変化)のレイテンシのみを短縮するTWリプロジェクションのバージョン。 VRアプリのフレームコンテンツを無限に遠くに投影されているように処理し、HMDの変換が再投影結果に影響を与えないようにする方法と考えることができます。 OTWは、頭部(およびHMD)の回転に過敏なVORのユーザーの正確に調整された感覚を補うため、VRの体験を大幅に快適にします。

PTW(Positional Timewarp)

6DoF TWとも呼ばれる、HMDの回転と平行移動(位置の変更)の両方の遅延を短縮するTWリプロジェクションのバージョン。これはVRアプリが送信したコンテンツの要素の距離を使用するOTWのスーパーセットと考えることができます。距離情報は、分析によってもしくはラスタライズされた深度など、さまざまな方法で推定できます。たとえば、Compositorがコンテンツが平らな平面または円柱弧(UI四角形など)に投影されていることを知っている場合、分析平面または円柱方程式を使用して、表面の各要素の距離を計算できます。深度ベースのPTWの場合、サンプリングされた距離情報は、特定のカラーバッファーに対応するVRアプリによって提供される、ラスタライズされた深度バッファーから収集されます。

STW(Synchronous Timewarp)

TWに使用されるソフトウェアスケジューリングの方法で、VRアプリがレンダリングされたコンテンツを送信した直後に、最終的なバレル(レンズ)ディストーションを適用するVR Compositorが同期的に実行します。この方法は、Asynchronous TWバージョンに置き換えられる前のDK2の頃のOculus Riftで簡易的に使用されていました。

ATW(Asynchronous Timewarp)

ATWはSTWとは対照的なTWに使用するスケジューリング方法のバージョンであり、それはVR CompositorがVRアプリのフレーム送信スケジュールとは独立して、理想的にHMDのリフレッシュレートで実行するというものです。これはVRアプリが必要なフレームレートの維持に失敗している場合でも、VRアプリが提供する最新のコンテンツを継続的に再投影することにより、視覚をスムーズにすることを主な目的としています。 TWのスケジューリングの側面は、使用されるリプロジェクションの方法(OTWまたはPTW)と直交しています。 ATWは、フレーム間のHMDレイテンシを一貫して低く保つのに役立ちます。

ASW(Asynchronous Spacewarp)

VRアプリが必要なフレームレートを維持できない場合に、HMDのビジュアルを一時的に滑らかにする機能。 ASWは、以前に送信されたフレームの内容から推定して、もっともらしい新しいフレームを合成することでこれを実現します。 ASWはATWに代わるものではないですが、むしろ一緒に動作します。そのため、ASWがアクティブな場合、ATWはレイテンシを削減し続けますが、ASWはATWが対応していないビジュアルの一部を滑らかにします。

Motion-to-Photon Latency

HMDモーションから、そのモーションを使用してレンダリングされたイメージがディスプレイに表示されるまでの経過時間。リアルタイムアプリケーションおよびVRで単に「レイテンシ」と呼ばれることもあります。 ASWとは異なり、PTWはコンポジションの最終段階で実行されるため、HMDのモーションレイテンシを低減するのに役立ちますが、ASWはパイプラインのかなり早い段階で起こります。

VOR(Vestibulo-Ocular Reflex/前庭動眼反射)

首の筋肉の動きを、目の回転の動きに逆らってリンクし、網膜上の画像を安定させる人間の反射。

VOR gain

首と目の筋肉間のVOR補正の反射調整。これは、特定の歪みプロファイルを備えたメガネの着用や、頭の回転中の目の平行移動による近接オブジェクトの余分な視差など、さまざまな理由で使用されます。 OTWとは異なり、PTWは、距離に基づいて視差を補正するため、VORゲインの忠実度を高めるのに役立ちます。

参考資料


翻訳しての雑感

Asynchronous Spacewarpは動画エンコーダが出す動きの予測情報を流用している、というのは意外であるものの理にかなった素晴らしいアイデアだと思います。またOculus DashのためにアプリがOculusランタイムに提供するようになった深度情報もフレーム予測に利用しているというのも興味深いです。ATW, ASW, PTWの関係もいまいちつかみにくかったですが、この記事で大分整理されました。

こういう詳細を調べていると、スタンドアロンのプラットフォームにもASWが欲しくなってきます。動画エンコーダを利用するASW 1.0ならOculus Questに実装できる余地はあるのでしょうか。ただ深度バッファを利用するPTWの方はモバイルGPUのアーキテクチャでは難しそうですね。

スポンサーリンク