技術

フォトンマップを利用した直接照明のテスト

朝一でアイアンマン3を観に行く前に直接照明のテストをしてたのでそのまとめ。

なんでここに来てまた直接照明なのよという感じだけど、これまでは大域フォトンマップだけで多少ボケててもいいからそれなりの画が1分未満ぐらいで計算出来ればいいなぁと思って頑張ってきたけど、やはりそれなりのクオリティと速度を両立するには少なくとも直接照明と間接照明の分離が必要だろうと思ったので、まずおさらいの意味も込めて直接照明を計算するコードを何パターンか実装してみた。
(大域フォトンマップだけでも、ある領域の放射束の分散(変動係数)を調べれば大きくぼかしていい所とそうじゃない所の区別が出来、適応的な放射照度キャッシュが実装出来るんじゃないかと思ってたけど、実際にやってみたらシーンによっては上手く行ったり、逆にキャッシュだけで数GBメモリを消費したりと安定しなかった。
それもそのはずで、そもそもそれが必要な分散なのか、単なる誤差なのか区別がつかないから安定しなかったんだろう。)

なんか堂々巡りしてる感じだけど、少しずつ理解が深まっていってると信じたい。

以前直接照明を実装したときは、常に決まった本数のレイを注目点から面光源にランダムに飛ばして、全ピクセル(厳密にはテクセルだけど)の色を計算してた。
その方法は重い上にノイズが酷いので使えない。
実装は楽なんだけどね。
ということでまず、面光源だろうと一発で放射輝度の近似計算を行う方法がないか考えてみた。

注目点から見て、面光源がどのくらいの立体角に相当するか計算すれば一発で放射輝度が計算出来るんじゃないか。という考えから以下のような方法を考え出した。

拡散面光源の場合
注目点p、面光源の重心g、光源から注目点へ向かうベクトルv = p – g、面光源の法線n、面光源全体の放射束w、面光源の面積aとすると、
見かけ上の面積(立体角) = a x dot(n, normalize(v)) / length2(v)
入射する放射輝度 = w / a * 見かけ上の面積

この方法はいちおう数式を考えながら導き出したんだけど、実は最後の「見かけ上の面積」を掛けるところを、最初は割るとしていて全然上手く行かなくて、じゃあとりあえず掛けてみるかっていう適当な考えでやってみたら上手く行ってるみたいってだけなので、間違ってるかも。
見かけ上の面積 = 立体角という認識が間違ってるのかも。
この手の方法は基本中の基本かもしれないし、それどころかもっといい方法があるかもしれない。

以上の方法を、この記事限定でとりあえず算術メソッドと呼ぶことにする。

ということで以下5パターンのテスト結果。

共通条件

フォトン数1万、近傍10個、収集範囲0.1m(シーンの縦横奥行きはそれぞれ5.5mぐらい)で推定。
数秒レベルで処理出来ないと意味がないと思うので、あえてかなりキツめの条件にした。

1. 光源から直接入射する放射束のみを記録したフォトンマップを直接可視化する方法。

ditest_1
1.82sec。まぁ酷いわな。

2. フォトンマップを使わずに算術メソッドで直接照明を描画する方法。

ditest_2
0.29sec。今回考案した方法の確認。遮蔽を考慮してないので当然影はない。

3. 影フォトンに負の放射束を載せ、算術メソッドの結果 + 影フォトンの近傍平均 として計算する方法。

ditest_3
1.07sec。正直見た瞬間笑ったw

4. 影フォトンと直接光フォトンの比率で光源の可視性を推定し算術メソッドの結果に乗ずる方法。

ditest_4
2.15sec。だんだん良くなってきた。

5. 半影領域(直接光フォトンと影フォトンを含む領域)のみ影光線を飛ばして可視性を推定し算術メソッドの結果に乗ずる方法。

ditest_5
3.85sec。影光線は10本。半影領域に限って影光線をとばしてるのでなかなか速い。ただしまだ目立つ問題点がある。

最初から分かってたけどやはり5番の方法が一番時間はかかるがそれ以上に質が高い。
ということで5番の方法だけもう少し設定を詰めてみた。
ditest_5_2
6.37sec。近傍25個、収集範囲0.25m。

箱の後ろにまわるとまだやばいところが若干あるんだけど、この時間でこの半影の質ならまぁまぁいいんじゃなかろうか。
ただ、シーンのほとんどが半影領域だとかなり重くなるような気もするがどうだろう。
レンダラならカメラが半影領域に近いとかでそういう状況は結構あるかもしれないけど、ベイカー的にはあまりそういう状況はないような気もする。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください