技術

放射束の格納にテクセルを用いる方法の問題点

テクセルはテクスチャ空間上で一様であるが、三次元空間でもそうであるとは限らない。
テクスチャをポリゴンに貼りつけると、テクセルの密度や歪み具合は各ポリゴンでまちまちに成り得る。

今までのプログラムでは、各テクセル毎に三次元空間上における面積を考慮した計算を行っていたため、テクセルの密度や歪みがまちまちであってもフォトンをたくさん飛ばせば(時間を掛ければ)、最終的にはそういった密度の違いが目立たない結果が得られていた。

しかし逆にフォトンの数が十分でない場合、ポリゴンごとのテクセル密度の違いによる収束スピードの違いが表面化することになる。
具体的には、同じ照明条件であっても密度の違うポリゴン同士で明るさに差が出るという問題が起きることになる。

さらに、ポリゴンごとのテクセル密度や歪みに差が無かったとしても、ポリゴンのエッジ付近のテクセル – その矩形領域のごく一部だけがポリゴンに含まれるテクセル – では、例えその面積を正しく考慮して照度の推定を行ったとしても、三次元空間においてその領域がとても小さいため、フォトンをたくさん飛ばしても、なかなかその領域に当たらず、そこだけ収束に時間がかかるという問題が起きることになる。
これは結果的にはポリゴンのエッジ付近に現れる暗い線・点線として表面化するだろう。

この問題を根本的に解決する方法としては、幾何形状から分離されたデータ構造(例えばkd木など)にフォトンの情報を蓄える、オーソドックスなフォトンマッピング法を利用するのが一番分かりやすい。
普通の方法で放射照度を推定し、放射輝度の計算結果をテクセルに書きこんでいくだけである。

ただそうすると、初期の段階(今現在から相対的にみた場合の初期。最終的な目的からみると今現在もまだまだ初期段階である。)であった、メモリ使用量の問題がまた現れることになる。

なのではやり、メモリ使用量がフォトン数に依存しないPPM法を利用したい。
そこで、三次元空間を一様なグリッドに区切って、グリッド単位で放射束を蓄積していくようにする。

この方法で問題になるのは、例えばシーンを1000x1000x1000のグリッドに分けたとすると、グリッドのデータ構造がポインタを一つ持つだけだったとしても、ギガバイトレベルのメモリ使用量になってしまうという点である。
メモリ使用量がフォトン数に依存しなくなる代わりに、シーンをどれだけ細かく分割するかに依存するようになってしまう。

ただ、必要なグリッドは物体表面に位置するものだけであり、全体からするとごくごく一部になるだろう。
使用してないグリッドについてのデータ量をゼロにすることができれば、この方法を実用することが出来る。

もったいぶった書き方をしてしまったが、未使用グリッドのデータ量をゼロにする方法は誰でも思いつくと思う。
辞書的なデータ構造を利用すれば簡単に実現出来る。
三次元空間上の座標値(と法線情報も含めた方がいいかもしれない)を一つのグリッドのサイズで割って、どのグリッドに属するか割り出したうえでハッシュ化するハッシュ関数を実装すればいい。
(といっても辞書を実現するためのオーバーヘッドは必ず存在するし、実装によっては未使用分も僅かにメモリを消費するものもある。きっかり使用してる分のメモリ使用量で済み、なおかつ挿入も検索もO(1)で済むような夢のような辞書の実装はないと思う。)

すでに実装しているテクセル単位の面積を計算する処理を用いて、テクセルの最小面積を求め、それに合わせてグリッドの細かさを決定すれば品質的な問題も起きないだろう。

さらにこの方法なら、もしかしたら近傍探索も効率化出来るかもしれない。

それにしてもこうなってくると、smallppmの方法により近づいてしまう。
ああいう実装になってたのにはちゃんとした理由があったという事だな。

コメントを残す

メールアドレスが公開されることはありません。



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

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