スクリーンスペースアンビエントオクルージョンまとめ
はじめに
こんにちは!アンビエントオクルージョンちゃんです。
前回の記事ではアンビエントオクルージョンの原理について解説しました。そこで、今回は主にゲーム等のリアルタイムアプリケーションにおけるアンビエントオクルージョンのアルゴリズムについて解説していきたいと思います。モダンなゲーム開発におけるグラフィックスの歴史とはオフラインレンダリングによるフォトリアルなグラフィックスをいかに30~60FPSで実現するかの歴史でした。アンビエントオクルージョンをリアルタイムで実現しようという流れも当然のものだったと言えるのかもしれません。
さて、リアルタイムの文脈でのアンビエントオクルージョンの実現方法は大きく二つに分けられます。一つは「事前計算による焼きこみ」で、もう一つは「AO項をスクリーンスペースで計算するもの」です。
前者は、所謂ベイクと呼ばれるもので、オフラインで十分な時間をかけてレンダリングしたい対象の各点におけるAO項を計算し、テクスチャ等の形式で保存しておきます。ランタイムではこの結果を参照し、ライティングに利用します。例えば、静的な建物などのAO項は、ランタイムで変化しないと考えられるので事前計算によるものが使われることが多いようです。
後者は、今回とりあげるもので、基本的に事前計算を必要としません。アルゴリズムの入力として、各ピクセルの深度(デプス値)を記録したデプスバッファや、法線を記録した法線バッファなどが必要になります。デプスバッファは現代の一般的なレンダリングパイプラインでは必ず使いますし、Deferred Renderingを行っていれば法線バッファなども容易に手に入ります。こういった意味で、スクリーンスペースアンビエントオクルージョンは既存のレンダリングパイプラインに追加することが比較的簡単なアルゴリズムだと言えます。
さて、オフラインで事前計算するアプローチの方が基本的に高品質なのですが、「動的なオブジェクトによるAOに対応できない」「ベイクした結果のストレージコストも馬鹿にならない」といった問題があります。前者はもちろん、後者については、特にオープンワールドゲームのように広大なレベル(ステージ)が舞台になるゲームにおいては顕著な問題となります。そこで、事前計算を必要とせず、ランタイムで得られる情報のみで計算を完結させるスクリーンスペースの技法が活発に研究されているわけです。CryEngine2において採用されたSSAOがこの主のアルゴリズムの源流とされることが多いですが、FarCryのようなオープンワールドゲームでは事前ベイクをなるべく少なくしたかった、というような背景があって開発されたのでしょう。
また、スクリーンスペースのアルゴリズムはスケーラビリティが良いという性質もあります。アルゴリズムの計算量はスクリーンの解像度依存であり、レンダリングしたいシーンのオブジェクトや頂点数には依存しません。これは、高密度なシーンに対しても効率的にAOを計算できることを意味します。
今回は、A Comparative Study of Screen-Space Ambient Occlusion Methodsというウェブページの情報を基に、編集・追加・新しい図の作成を行い、各解説を作成しました。以下の六種のアルゴリズムも上のページで紹介されていたものを選んだものです。合わせて読んでいただけるとより理解が深まると思います。それでは、各アルゴリズムについて見ていきましょう。
CryEngine2 Ambient Occlusion
その名の通り、CrytekのCryEngine2で最初に導入されたアルゴリズムで、スクリーンスペース系のアンビエントオクルージョンアルゴリズムの先駆けとなるものです。まず、AO項目を計算したい対象のピクセルをpとします。このを中心とした球を考え、球の内部にサンプリング点をランダムに生成します。
デプスバッファ上で、各サンプリング点に対応する位置を計算します。すると、サンプリング点のデプスバッファ上でのデプス値を得られます。(これは、カメラからサンプリング点に伸ばしたレイとシーンの交点の位置のデプス値になります。)この値と、サンプリング点の「実際の」デプス値を比較します。この結果、の方がよりもカメラ側にあれば、サンプリング点はシーンの物体によって遮蔽されています。逆に、の方がよりもカメラ側にあればサンプリング点はシーンの物体によって遮蔽されていません(カメラから可視)。
以下の図では、緑のサンプル点が可視、赤のサンプル点が遮蔽ということになります。
このあたりの考え方は、シャドウマップにおいて、対象点の、シャドウマップから得たデプス値と実際のデプス値を比較することで遮蔽判定するのに近いでしょう。
このようにして、各サンプル点が遮蔽されているのか可視なのかを判定していきます。この時、遮蔽されている点の割合が大きければ大きいほど、における環境遮蔽度も大きいと推定されます。よって、この割合をAO項の近似とします。
この手法は、デプスバッファをサンプリングするだけでAO項を計算できるため、非常に高速であることが知られています。しかしながら、実際にはノイズをはじめとした各種アーティファクトが大きくなりがちで、最終的にブラーをかける必要があるようです。SSAOのアーティファクトとその対策についてはこちらが詳しいです。
参考ページ
Finding Next Gen – CryEngine 2 by Martin Mittring 2007
床井研究室 - SSAO (Screen Space Ambient Occlusion)
StarCraft II Ambient Occlusion
2008年に発表され、StarCraft IIに実装されたSSAOがあります。これは、CryEngine 2のSSAOに非常に近いのですが、CryEngine2のものが球の内部にサンプリング点を生成したのに対してこちらはの法線の方向の半球内部にサンプリング点を生成するという点が違います。
サンプル点を生成した後の処理はCryEngine2 SSAOと変わりません。CryEngine2のSSAOは球内にサンプリング点を生成していたため、半球の下部分のサンプリング点は基本的に全て遮蔽されてしまい、遮蔽・可視判定をする意味のない無駄なサンプルでした。StarCraft IIの手法はサンプリング点を半球内に生成することでサンプルの無駄を削減したより効率の良い手法です。
参考ページ
StarCraft II Effects & Techniques by Dominic Filion and Rob McNaughton 2008
CryEngine2 SSAO同様、こちらのサイト(Know your SSAO artifacts)が参考になります。
Horizon-based Ambient Occlusion
俗に言うHBAOです。この手法は、デプスバッファに対してレイマーチングを行うことで逐次的にサンプリングを行い、サンプリングしたデプス値との位置関係より周囲のジオメトリ構造を推定、地平角度を求めます。
レイマーチングの方向は、視線方向に直交する方向を選びます。
レイマーチングの方向にデプスバッファをサンプリングしていき、デプス値を取得、からその位置へのベクトルを考え、法線との角度(=地平角度)を計算します。新しい地平角度がそれまでの地平角度より小さければ、角度を更新します。
もし新しい地平角度がそれまでの地平角度より小さくなければ、更新はしません。(赤い点が更新しなかったサンプリング点)
以上を繰り返し、最終的な地平角度を求めます。この地平角度は、の周囲の遮蔽度を表現していると考えられるため、AO項の近似に使うことが出来ます。
実際にはを始点として、視線方向に直交する方向を複数用意し、各方向にレイマーチングしてその結果の平均を地平角度とします。大体四方向程使うようですが、全てのピクセルで同じ方向だとアーティファクトが発生するため、ピクセルごとにランダムに(視線方向を軸として)回転させます。
この手法は高品質な結果を得られますが、レイマーチングの際に大量のサンプリングを行う必要があり、計算コストが大きい手法です。
参考ページ
Image-space horizon-based ambient occlusion by Louis Bavo, Miguel Sainz and Rouslan Dimitrov 2008
Image Space Horizon Based Ambient Occlusion by Bryan Dudash(CEDECの講演で、日本語資料)
Volumetric Obscurance
これは体積積分に基づいた方法です。従来のアンビエントオクルージョン手法ではサンプリングは基本的に点によって行われていましたが、この手法は、まずを通る視線方向に垂直なディスクを考え、そのディスク上にサンプル点を生成します。次に、各サンプル点を通る視線方向に平行な線分を考え、各線分をサンプルとします。
この線分はを中心とする球の内部にのみ存在し、デプスバッファからデプス値を取得することで、各線分がどの程度シーン内部(遮蔽部)に存在するのか、可視部に存在するのか、を判定できます。以下の図では、各サンプルラインの内、緑の部分が可視、赤の部分が遮蔽であることを示しています。
あとはこの結果を使って体積積分することで、を中心とする球の内部の、どの程度の割合が可視なのか、遮蔽部なのかを求めることが出来ます。
この結果をAO項の近似に使います。
従来のサンプリングを点のみに依存していたやり方では、各サンプルは遮蔽or可視の二値状態しかとりませんでした。結果として、カメラ位置のわずかな変化によって状態が大きく変化し、結果も大きく変化してしまうという時間的な非一貫性が問題でした。しかし、この手法では各サンプルは体積計算のための遮蔽度(あるいは可視度)を持つことになります(上の図で言うところの緑の部分と赤の部分の割合)。このようにサンプルを線でとらえることにより、各サンプルの状態は連続的になるため、他称カメラ位置が変化した程度で急激に結果が変わることがなくなり、時間的な頑健性が増した手法となっています。
参考ページ
Volumetric obscurance by Bradford James Loos and Peter-Pike Sloan 2010
Alchemy Ambient Obscurance
この手法は、まずディスク上にサンプルを生成し、これをシーン表面にデプスバッファを使って投影します。次に、投影された各サンプル点からベクトルを作ります。
そして、それぞれのと法線の内積を計算し、その平均を求めることでAO項を近似します。各との内積はベクトルと法線の成す角のコサインであるため、この値はの周囲の遮蔽度を大まかに近似していると考えることが出来ます。つまり、Horizonal-Based AOでいうところの地平角度の大ざっぱな近似になっているということです。
この手法は、内積計算が高速に行えるという事実により、非常に効率の良いものになっており、また、生成されたサンプルは効率よく遮蔽度の計算に使われているため他の手法に比べてサンプル数も少なく抑えることが出来ます。
参考ページ
The alchemy screen-space ambient obscurance algorithm by Morgan McGuire, Brian Osman, Michael Bukowski and Padraic Hennessy 2011
Unreal Engine 4 Ambient Occlusion
Unreal Engine 4で使われた手法で、これも地平角度の計算を試みます。この手法では、サンプル点が同時に二つ生成されます。それぞれのサンプル点はこれまでと同様に、デプスバッファを使ってシーン表面に投影されます。投影後のサンプル点をととします。次に、AlchemyAOのように各サンプル点との間にベクトルをつくり、このベクトルを用いてが近似されます。
AO項の計算時、ピクセルごとの法線バッファから法線を取得し、法線方向の半球を考え、地平角度をこの範囲に制限することで、より高精度なAO項の近似が可能になります。
参考ページ
The Technology Behind the “Unreal Engine 4 Elemental Demo” by Martin Mittring 2012
まとめ
SSAOの各種技法のキモになるのは、「いかに少ないサンプル」で「高品質な結果」を得るかどうか、です。このことから、一つのサンプルから最大限情報を利用するタイプのアルゴリズム(Alchemy AOやUE4AO)の方が、一つのサンプルについて単純な遮蔽・可視の二択しか考えないタイプのアルゴリズム(CryEngine2 SSAO等)よりも効率が良いようです。
近年、Multi-view Ambient Occlusion with Importance Samplingのように、既存のアルゴリズムを大きく変更せず、複数のデプスバッファの情報を基により高精度なAO計算を行うような手法も出てきています。さらに、2013年に発売されたゲーム、The Last of Usにおいては、環境光からの影響のための遮蔽計算をワールド空間でレイトレーシングを行うことで高精度に計算する、といったことが行われています。(Lighting Technology of "The Last Of Us")アンビエントオクルージョンの研究は今後もますます活発になっていくことでしょう。