VRのレンダリングについて

Oculus Riftをはじめとする、VR機器のレンダリングについて考えてみたいと思います。

参照

DK2 and Latency Mitigation [Cass Everitt, HPG2014]
http://static.oculusvr.com/website/dk2-latmit-hpg2014-cass.pptx

Oculus Rift DK2のスペックについて

  • 広いFoV。100度
  • 19×10解像度のOLEDスクリーン
  • Displayのリフレッシュレートは75FPS
  • 短残光(2-3ms)ディスプレイ。走査は右から左
  • IMU(慣性計測装置)のリフレッシュレートは1kHz
  • Positional Tracking. RefreshRateは不明。たぶん~100Hz latencyは19ms
  • VR光学系のレンズによってもたらされる歪曲収差、色収差
  • Cass氏のスライドから読み取れるのは、シーンのレンダリングと、VR光学系の補正のためのリサンプリングは非同期にするべきだということです。上記の通り、Displayは75Hz, IMUは1kHz, Positional Trackingは100Hzと、全ての機器が違うレートで動作しています。レンダリングとリサンプリングを非同期にすることで、リサンプリング開始のタイミングで手に入る、最新のIMU/PositionalTrackingの情報を用いて、出力に補正をかけることが出来ます。
    加えて、万一レンダリング側が75FPS以下になった場合でも、同じレンダリング結果に再度リサンプリングを行うことで、IMUとPositonalTrackingによる出力の更新が可能と思われます。
    さらに、ディスプレイは、右から左に走査するため、画面の右と左には時差があります。V-Blank(?)がどの程度あるか分かりませんが、数ms程度は時差があるはずです。そのため、視点の水平方向のPanの速度と方向に合わせて、水平方向のFovを調整を調整する必要があるそうです。従って、シーンのレンダリングのパスでは、VRの実視野角に対して、少し余裕を持たせてレンダリングし、リサンプリングの際の補正のための幅を確保する必要があります。

    広視野角のレンダリングについて(2014/07/23訂正)

    DK1に関しては、Webで検索する限り、垂直視野角が90度で水平視野角が100~110度だそうです。これらの値は、観測者の目の位置に依存して、110度の視野角は、まつ毛がレンズに触れるほどの位置だそうです。
    DK2に関してはnominal 100度という表記しか見当たりません。結局観測者の眼球の位置依存なので、正確に定義することはできないようです。
    Planner Projectionの、視野角に対するピクセル分布の偏りは、FOVの角度が大きくなれば次第に大きくなっていき、RenderTargetの解像度には依存しません。また、視野の中心部が、ピクセルあたりの視野角が最も大きくなり、分解能が低いです。
    分布の偏りはFOVのTangentの微分で簡単に計算できます。
    FOVが90度なら中心付近と、周辺付近の視野角の分布の差は丁度2.0倍になります。
    FOVが110度なら分布の差は、ほぼ3倍になり、FOVが120度なら4倍になります。
    結局のところ、FOVが90度を超えたあたりから、急速にPixelの分布が悪化してゆくのがわかります。
    DK2用のレンダリングで、リサンプリング時に視野に補正を加えるとするならば、100度+αのFOVを設定する必要があると思います。
    片眼に割り当てられるリサンプリング後の解像度はFullHDの半分にあたる960×1080で、実際にレンズを通じて見える部分はこれ以下のはずです。リサンプリング前のRTにどの程度の解像度が必要かはわかりません。以下は推測です。
    もしもDK2のレンズが上記解像度のRTを視野角に対して均一な分布でPixelを配置するならば、水平、垂直で各々
    100/960 = 0.104度
    100/1080 = 0.093度
    となります。
    これをPlannerProjection一枚のレンダリングで実現するとするならば、
    リサンプリング前の上下視野角を100度確保した場合は、
    tan(50) / tan(0.104) * 2 = 1313
    tan(50) / tan(0.093) * 2 = 1468
    となり、片眼1300×1400程度のRTが必要なようです。約1.7MPixelです。
    リサンプリング時の視野の補正の幅を十分に確保した場合として、上下視野角110度を確保した場合は、
    tan(55) / tan(0.104) * 2 = 1573
    tan(55) / tan(0.093) * 2 = 1759
    となり、片眼で約2.6MPixelになり、FullHDを上回ります。

    さらにサンプリング周波数という観点から考えると、これの2倍の解像度を確保したいところです。PlannerProjection1枚でこれを確保すれば、ピクセル数は4倍となります。両眼で約20MPixel程度のレンダリングになりそうです。しかし、4K解像度2枚以上のピクセルを75FPSでレンダリングするのはあまり現実的とは言えません。

    中央の分解能を上げる

    人間の目の分解能は、視野中央部が高く、周辺部が低くなっています。ならば、レンダリングもこれに従って行われるべきです。しかし、双曲面などに投影すると、非線形な投影となり、ラスタライズは困難になります。
    そこで、Planner Projectionで投影面の周辺部の分解能が高くなることを利用し、CubeMapの角の部分が画面の中央に来るように配置してみます。VRのレンダリングでは、最終的にはリサンプリングが行われるので、中間の投影面が向いている向きよりも、確保されている分解能の方が重要だと思います。リサンプリングの際にCubeMapの面の境界でどの程度のアーティファクトが出るかは未知数です。
    CubeMapにレンダリングすることで、リサンプリング時には、視線ベクトルを用いて、そのままCubeMapをサンプリングすれば、リサンプリングが行えるはずです。CubeMapの境界も、SeamlessCubeMapの機能があれば、隣り合うMap間で補完された値をサンプリングすることが出来るので、品質も期待できます。
    ただし、必要となるRTの範囲が矩形ではないので、Stencilなどを用いて、不要なPixelのレンダリングを行わないようにする必要があります。また、確保した3面のRTのうち、半分程度は使われること無く無駄になると思います。
    下図はそのイメージ図ですが、実際にはCubeMapをPlanner Projectionすることはないので、このイメージを作るわけではありません。

    cube_proj_120

    機会があれば、ぜひ試してみたいと思います。