2013/05/20

SSAO に再挑戦していた

数年前に SSAO (Screen Space Ambient Occlusion) を実装しましたが、自身の実装と解釈に誤りがあると認識しつつも放置したので、SharpDX ベースの自作フレームワークに入れるために、再度、納得できる質まで改善していました。

数年前に参考にした実装は下記サイトであり、今回もこれをベースにしました。
Game Rendering - SSAO: http://www.gamerendering.com/2009/01/14/ssao/
大まかな処理の流れは、Ray Marching Ambient Occlusion を基礎とし、法線による平面間に対する判定を除去しているのだと思います (実装上は法線差による閉塞度に対する重み付けの調整)。

今回は、上記サイトの実装をベースにしつつ、深度を線形深度マップ (Linear depth map) へ置き換え、線形深度からビュー空間座標を再構築して判定するような実装を組んでいました。その他、シェーダ内でハードコードされた球面内サンプル点や、テクスチャ ファイルとして用意しているランダム法線マップをなどを C# 側で生成してシェーダへ渡したりしています。

相変わらず、テストに使用しているシーンが簡素過ぎますが、以下、ひとまずは納得できた結果の画像です。
ブラー前 SSAO マップ
ブラー後 SSAO マップ
SSAO 適用シーン
レイによるサンプル数を 8 として SSAO マップを生成しています。生成された SSAO マップへのブラーでは、バイラテラル フィルタの変形バージョンを 3 回適用しています。1 回の適用でもそれなりですが、3 回程適用すると十分な綺麗さが出る感じがします。なお、単純に色の差異でバイラテラル フィルタを適用すると期待するブラーにはならないので、深度マップを参照して深度の差異で重みを変化させています。加えて、法線の差異でも重み付けを変化させているため、厳密にはバイラテラルではないのだろうと思います。法線を考慮せずとも十分なブラーを得られますが、法線差異を制御するための標準偏差を色々と変化させてみると微妙な調整ができるので、これで良いとしています。

負荷を下げるために SSAO マップのサイズを小さくし、シーンと合成する前にアップサンプリングしてみたりなどもしましたが、単純なアップサンプリングではシーンとの合成時に解像度の差異から汚くなる部分が出てくるため、少し考慮が必要なのだろうと感じています。
追記: と思っていたら、どうも僕のダウンサンプリング実装に誤りがあり、修正して適用してみると、悪くない結果でした。3D グラフィックスは、僅かな値の差ではそれなりに稼働してしまうので、デバッグが怖いですね。
何にせよ、納得できる所まで持ってこれて、心底安心できました。

0 件のコメント:

コメントを投稿

libgdx いじり

Google が提供している Java 版の Tango Examples は Rajawali をベースにしているため、自分が仕事で開発する Tango アプリも Rajawali ベースとしていましたが、最近は libGDX への移行を進めています。一応、要点については移行が...