2012年01月15日

フォトンマッピングについて その2

フォトンを飛ばす方向についてですが、通常乱数を使って生成します。

しかし、平面光源からの光や、光沢のある鏡面反射の場合、単純な乱数ではなくcosθに比例した割合で方向ベクトルを生成する必要があります。

フォトンマッピング本では、基本的に極座標系で方向ベクトルを定義しており、θとφの2つの偏角でcosθに比例した方向ベクトルを生成できるとありました。

vec_001.png

上記の式でθとφを決めたのですが、それをベクトルに戻す場合WikipediaにはZ軸を基準とした式しか載っていませんでした。

http://ja.wikipedia.org/wiki/%E6%A5%B5%E5%BA%A7%E6%A8%99%E7%B3%BB

この式ではZ軸方向ベクトルの周りにcosθ比例したベクトルしか得られません。

実行結果

cornell_008_0.png

光源を中心に設定し、中心からZ軸方向(奥)にcosθ比例したベクトルへのフォトンの放出

しかたがないのでクォータニオンで回転させることにしました。

http://www015.upp.so-net.ne.jp/notgeld/quaternion.html

クォータニオンで回転させるためには、回転主軸ベクトルと、回転させる角度が必要です。この二つは外積と内積を使用することで求めることができます。

vec_002.png vec_003.png

実行結果

cornell_008_1.png

光源を中心に設定し、中心からY軸負方向(下)にcosθ比例したベクトルへのフォトンの放出

以上のように、一応できましたが、Z軸方向に一旦作成してから回転させるのは何か気持ち悪いので、一発で生成できる方法をご存知でしたら誰か教えてください。

web拍手 by FC2
posted by シンドラー at 00:19 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年01月08日

フォトンマッピングについて その1

冬休み辺りでフォトンマッピング[1]を試してみることにしました。
Twitterに呟くだけだと参考サイトなどを忘れてしまいそうなのでメモ代わりにまとめていきます。

フォトンマッピングでは、フォトンの格納と探索を行うデータ構造が必要で、フォトンマッピングの本ではkd-treeを用いるようになっていました。
そのため、最初にkd-treeの実装を行いました[2]。

kd-treeを作るときに各軸方向の中央値を見つける必要があるのですが、面倒だったのでフォトンをstd::vectorに入れてsortで並べかえて真ん中のデータを使用しています。
本来は「線形中央値探索アルゴリズム」なるものを使用するのだと思います(by Wikipedia)。

次に近傍フォトンの探索ですが、最大ヒープ法(優先度付き待ち行列)で指定した個数の近傍フォトンを見つけることができます。
この部分は[3]がとてもわかりやすかったです。

実行結果

kdtree5000-3d.png kdtree5000-1000.png

左は正規分布に従って生成したフォトンの近傍フォトンを示したものです。
3次元のものを2次元画像にしているだけで取りこぼしているわけではありません。

右は2次元、ランダムに5000点座標を決めて中心から近傍1000個のフォトンを探索した結果です。

次に、実際のシーンでフォトンを飛ばしていく必要があります。
シーンは有名なCornell Box[4]もどきを作って試すことにしました。

フォトンは確率的に反射や透過、吸収が行われていくということで、フォトン(光線)とシーン上の物体との衝突判定が必要になります。
結局衝突判定がでてきて面倒ですね。その辺りのお話はその2でまとめたいと思います。

参考文献
[1] フォトンマッピング:http://ssl.ohmsha.co.jp/cgi-bin/menu.cgi?ISBN=4-274-07950-3
[2] http://d.hatena.ne.jp/higepon/20101024/
[3] http://ufcpp.net/study/algorithm/col_heap.html
[4] http://www.graphics.cornell.edu/online/box/data.html
web拍手 by FC2
posted by シンドラー at 14:53 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする