技術

フォトンベイカー(仮)進捗その10

前回に引き続きまたもやフォトンの反射率の計算や反射後の出力の計算、放射輝度推定の方法を変更した。
というのも前回参考にした方法でももう少し頑張ればまともな絵が出せそうな気はしてたが、それ以前に処理速度の低下が激しかったので内心やばいなと思ってた。

The 迷走中、という感じだが、しかし今回はそれが功を奏してやっとまともな絵が計算できるようになった。しかも省メモリで早い。
p10m_184sec_max

これは分類上「フォトンを直接可視化する方法」になると思うんだけど、フォトンを一千万個も使ってるにも関わらず、処理時間は3分4秒、メモリ使用量は以前一千万フォトンやったときの5分の1以下。

この方法を自力で考え出せたとしたらどんなに素晴らしいかと思うけど、やはり今回もネタ元が存在する。

参考にしたのは以下のページで公開されている smallppm.cpp というソース。
Himatsubushi

この1ファイルだけのたった128行で、プログレッシブフォトンマッピングという方法で箱のシーンを描くプログラムとなっている。

私が今やってるこのフォトンベイカーを作ろうと思ったきっかけは色々あるんだけど、その中のひとつとして、
ParthenonというGIレンダラを使ってみて「もっと自分が使いやすいものを作ろう(機能・性能的に劣るだろうけど)」と思ったというのがある。

で、今回参考にしたソースの作者とParthenonの作者は同一人物なんですね。
もうね、神と崇めたいくらい。

で、昨晩寝る前に偶然 smallppm.cpp を発見してからとりあえず寝て、用事があったので朝から出かけて寿司食ったりして、昼過ぎから作業を開始し2,3時間で解読して、半日程度で自分のプログラムに組み込んだ結果が冒頭の画像。

自分のプログラムはレンダラではなくベイカーなので、物体表面の位置情報や法線情報はすでにテクスチャ化されており、今回組み込むにあたって専用のデータ構造は用意せず、輝度の情報もそのままテクスチャに書き込むようにした。
テクスチャを使ってる関係で、全体的に単精度浮動小数点を使ってるのでもしかしたら精度の影響が画像に出てるかもしれない。
今後問題が出るようなら一部のデータはvector<double>にいれてしまうかも。

smallppm.cpp はコードを短くするためにちょっと読みにくくなってるので、読みやすくするために改行やスペースをきちんとして重要な変数名を省略無しのバージョンに変更した程度のリファクタリングをしつつ解読したけど、リファクタリングしてしまえば構造が素直で非常に読みやすかった。
(コードを短くするためだと思うけど物体を全部球で表現してるのが面白いと思った。(平面に見える壁も巨大な球の一部))

大まかに smallppm.cpp の処理内容を説明すると、(自分のプログラムはこれとはまた別の流れとなっている)

  1. まずカメラを始点として画素にレイを飛ばして、拡散面にぶつかったらその地点を表すデータ(地点データ)を生成。
  2. 次に光源からフォトンを飛ばして物体表面にぶつかったら、その衝突地点をもとに地点データを検索し(ハッシュを使うので速い)、該当のデータに輝度の情報を書き込む。
  3. フォトンを飛ばし終わったら、地点データを全て舐めて最終的な画素の色を決定。
  4. ファイルに出力。

となっている。
肝は2の部分で、以前に同じ地点に書きこまれた輝度情報と新しく書き込む輝度情報をうまい具合にブレンドすることによって、フォトンの情報を何回書きこんでもデータの増大を招く事が無く、それによって大量のフォトンを扱うことを可能にし、フォトンを増やせば増やすほど精度が上がっていくという戦略を積極的に選択することができるようになっている。
フォトンマップにkd木とかを使う方法だと、フォトンの数に比例してデータ容量が増えるので大量のフォトンを一度に扱うのが難しい。
モンテカルロ法は数が命なのでこれはかなり重要な点。

フォトンをひとつ生成しては反射しなくなるまでトレースする、というのを何回でも繰り返せるため、フォトンのデータは一度にひとつだけあればいいのでメモリにとてもやさしい。
メモリ使用量が、フォトンの数ではなく地点データの数(細かさ)に依存する方法といえる。
地点データ ≒ 最終的に欲しいもの はだいたい限られてるのでそちらに合わせるのは理にかなってると思う。

自分のそんなに速くないマシン&特に高速化してないコードで5,6分で五千万フォトンを扱えるので、1億とか10億でも現実的な時間&リソースで実行可能なものと思われる。(まだ試してない)
もしかしたら単精度の問題が表面化してしまうかもしれないけど。

追記

一億フォトンで試してみた。実行時間は30分ちょっと。
p100m_1847s_max
一千万のときより確かにノイズは減ったけど、まだ目立つ。
テクスチャにベイクしたものを貼りつけてるため、物体表面のザラザラ感の表現に見えなくもないが、単にフォトンを増やすという方向性ではノイズの除去に時間がかかり過ぎる。
やはり別の方法(ファイナルギャザリングとか)を併用する必要がある。

コメントを残す

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



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

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