バイラテラル・アップサンプリング(Bilateral Upsampling)のメモ
参考文献
特徴
- まず,「オフスクリーンパーティクル」とはパーティクルだけ低解像度のカラーバッファに対してダウンサンプリングしたデプスバッファを使ったレンダリングをして, 後でフル解像度のバッファと合成する手法です.
- 下図の左はフル解像度でパーティクルのデプステストを行った場合です. 一方で下図の右のオフスクリーンパーティクルではダウンサンプリングしたデプスバッファを使ったデプステストを行っているため, 結果をそのままアップサンプリングするとギザギザのアーティファクトが発生しています.
- 上では「オフスクリーンパーティクル」というようにパーティクルの話でしたが, スクリーンエフェクトについても低解像度のバッファに対して処理してアップサンプリングする方法が同様に使えます.
- 下図は 球にする AO の処理(Sphere AO)を適用していない状態です. ( "Sphere AO" について)
- 一方で, Sphere AO を 1/2 * 1/2 解像度 ( 640x480ピクセル)で処理してから, 後述するバイラテラル・アップサンプリングで参照した場合, 絵のクオリティがそんなに変わらないにも関わらず, FPS が 62 -> 135 と 2 倍近く速くなっています.
図による説明
- 下図の左がバイリニアフィルタによる重み, 下図の真ん中はデプス差分による重み, 下図の右側は法線の違いによる重みです.
- 実際に下図のようなデプスの差分や法線の向きによる違いがある場合についてです. 下図の右側の上からバイリニアフィルタによる重み, デプスの違いによる重み, 法線の違いによる重みです. 実際に低解像度のバッファを参照するときにはこの 3 つの重みを乗算して利用します.
- 更に拡大したのが下図です. 下図の右側の列はバイリニアフィルタのみでアップサンプリングした場合でシルエットに白い線が出てしまっています.
実装
- まず, 低解像度バッファの 4 テクセル分のバイリニアフィルタ相当の重み(vBilinearWeights)を用意しておきます.
- 下のコードではフル解像度バッファの法線(vNormalHiRes)と 低解像度バッファの 4 テクセル分の法線(vNormalCoarse[0][1][2][3])との比較をして, 重み(vNormalWeights[0][1][2][3])を求めています.
- この時点で, フル解像度バッファの法線バッファへのテクスチャフェッチ1 回と, 低解像度バッファの法線バッファへのテクスチャフェッチが 4 回発生します.
- 下のコードではフル解像度バッファのデプス(fDepthHiRes)と, 低解像度バッファの 4 テクセル分のデプス(fDepthsCoarse[0][1][2][3])を比較して, 重み(vDepthWeights[0][1][2][3])を求めています.
- さらに, フル解像度バッファのデプスバッファへのテクスチャフェッチ1 回と, 低解像度バッファのデプスバッファへのテクスチャフェッチが 4 回発生します.
まとめ
- そのまま実装するとテクスチャフェッチ数が多くなるので, コストに見合った場合に使った方が良さそうです.
- あるいはテクスチャの RGBA にパックしてフェッチ数を減らしたり, 使うシーンであまり効果のない判定処理は飛ばしてしまう方法もあると思います.