~■はじめに今までの画像は、ライティングがいかにもうそ臭いものでした。この点も修正して、実写らしい見た目になるようにがんばって見ましょう。今回のプログラムは、次のものです。DirectX9)まぁ、いつものように適当にファイルが入っています。出力されるフレームワークのファイルは紹介を省かせていただきます。ダイアログを管理するクラスのヘッダあと、実行ファイル、リソースファイル、プロジェクトファイルが入っています。■何やってるの?モンテカルロ法とは、乱数を使って計算を何度も行い、その結果の合計を試行回数で割った平均(アンサンブル平均)を正式な計算の結果として使うというものです。レイトレースに関していえば、本来は、レイが物体にあたったときは、BRDFに従ってさまざまな方向からの光を寄せ集めてレイに入射する光を計算しなくてはなりません。それはめんどくさいので、大まかに反射、屈折および拡散の現象に分けて、それらの反射率に従って1つのレイを飛ばして、色を求めます。のどの種類の反射をするのかは乱数を振るまでわからないので、ロシアンルーレット式の方法とも呼ばれます。拡散反射の場合には、四方八方の光を調べなくてはならないのですが、ここにも確率的な考え方を取り入れます。一度の試行では、拡散反射についてでもレイを1方向だけしか飛ばしません。方向をランダムにすることによって全方位からの光を取り入れます。つるつるな物質を考えます。2:8の割合で光を薄く反射する物質だとします。0.0この物質にレイがあたったとき、まず0~1の範囲で乱数を計算します。小さな時は、次のレイは反射ベクトルに従って反射します。0.2~1.0の時は、拡散反射の計算を行います。ばらばらな方向にレイを飛ばして多重散乱の計算を行います。あと、今まで出てこなかった材質について考えなくてはなりません、ライトのような光を発する物質です。このような物質へレイがあたった場合には、そこから先はレイは反射せずに、ライトの色をレイに入射する色に与えて、計算を終了します。いうか、今回は、Blinn-Phongシェーディングは捨て去ってしまいたいので、レイの計算が終わる方法は(レイが物体にあたらないで空間を突き抜けた場合以外には)放射する物体へ当たるしかほかにありません。視点から出たレイはいろいろな物質を反射して、最後にライトに交差した時点で計算は終了し、その経路にわたった色がその試行の色として採用されます。いっても、何度も反射して光にたどり着かないと計算時間を食うだけなので、適当な回数の反射で計算を打ち切ることにします。CG的には、放射しつつ光を反射する材質もあるでしょう。したがって、放射の割合も確率事象に含める必要があります。誤差が消えていき、無限回の試行を行ったとすれば正しい値に収束することが知られています(中央極限定理)。ライトのような光を出す物質もプリミティブで表現することにします。鏡面反射は使わないので、(主に)拡散反射のための色のパラメータを1つだけ残しておきました。}Material;たとえば、次のようなデータになります。項に0が追加されるだけです。1.0で、その他が0になります。色のパラメータを光の強さにも使うことにしました。■色の計算さて、レイトレースする部分を見ていきましょう。探査する深さが深くなりすぎたときに適当に計算を打ち切るための判定を行います。今回は、反射、屈折の時には深さは深くしないで、拡散反射のときだけ再帰の深さが深くなるようにしました。FALSE;}そしたら、交差判定です。ここはいままでも出てきたように計算します。v);オブジェクトにあたらなかった場合は、背景色を出力します。各確率から、今回の試行がどのプロセスを行うか決定します。具体的には、それぞれの確率の和から乱数の上限を決定して、乱数の得られた値からどの種類の反射を行うか決定します。ちなみに、吸収する確率は、1-cd-cr-cnになりますが、吸収の効果は今回はロシアンルーレットでは考慮せず、最後に色を出力するときに考慮します。拡散する時には、レイはランダムに飛ばします。内積を計算して、レイの方向が法線ベクトルと反対向きなら、レイの向きを反対にして、物体の面の方向にレイを飛ばすように調整します。ランダムな方向にレイを飛ばして、再帰的に得た色の成分は、物体の色と、法線ベクトルとレイの方向の内積を掛けて出力する色とします。これは、ランバートの余弦則そのままです。}反射する場合は、反射ベクトルを求めて、さらに探索します。}屈折の場合は、屈折ベクトルを求めて、再帰的にレイトレースします。no_refract:放射光は、マテリアルの色そのものになります。*(D3DXVECTOR3*)&pObj->m_material.COLOR_DIF;最後に、今までに計算した色をそれぞれの状況に応じて合成します。光の吸収率になるので、そうでない成分を出力するように調整するためです。}■画面の更新さて、モンテカルロ法は回数を重ねれば重ねるほど正確な画像に近づいていく手法です。したがって、何度も何度もレンダリングすることにします。関数を書き換えました。関数を使えば、ミリ秒単位で現在時刻を知ることができるので、関数が呼ばれた時刻を保存しておいて、短い処理を終えるたびに時間を計測し、その時間が1秒を超えていたら関数を終了するようにします。秒の時間分解能にしました。関数の中では、適当に状態を設定して、レンダリングの手順を整頓しています。ここで、ボタンが押されるのを待ちます。レイとレースするピクセルを左上に設定するなどのことをしています。ピクセルごとにレイトレースをします。