周辺の景色からのライティングを表現する環境マップによるIBLや、太陽などをモデル化する平行光源はシーンを構成する光源の一種としてかなり便利です。一方で、無限大を含むその特性は正しい取り扱いに注意を要します。特にNext Event Estimationや双方向パストレーシングなど、光源側からのサンプリングを必要とする場合には間違った実装に至りやすくなります。このページではモンテカルロレイトレーシングにおける無限遠光源の正しい扱い方について解説します。
「光源の出力と放射輝度の関係」でも紹介しましたが、シーン中のある点に対するライティングを考えるとき、無限遠光源は文字通り無限の遠方にあるので、そこにある方向から降り注ぐ光の量は(面の傾きや他の物体による遮蔽を除いて)点の座標には依存せず、光の入射方向にのみ依存します。
上図にその理屈を示します。例として有限の大きさの半球の内側からシーンが照らされているとします。シーン中の2点 $ \vx_A $, $ \vx_B $ に降り注ぐ光の量について考えます。左側の図のように、シーンが光源に対して相対的に大きい場合は光源の各点に対する距離が2点それぞれで全く異なるので、ライティング結果もそれに応じて全然異なるはずです。$ \vx_A $ のほうが $ \vx_B $ よりも明るくなるでしょう。一方で右側の図のように光源の球が大きくなる(もしくはシーンが小さくなる)と、光源の各点に対する距離と方向が2点それぞれで大して変わらなくなるので、ライティング結果も同じようになります。そして光源が無限大に大きくなった場合を考えると、ある点に入射する光はその方向のみに依存するようになります。
ある点に入射する光の量がその方向にしか依存しないということは、逆に言えば、シーンのどこを考えても遮蔽が無ければ同じ量の光エネルギー(放射束)が到達するということです。
Next Event Estimationも使わない単純なパストレーシングの場合の、環境マップによる無限遠光源の扱い方は非常に単純です。ある点 $ \vx $ から通常通り何らかのPDF $ p_\sigma(\vomega) $ にそって入射方向 $ \vomega_i $ をサンプリングして、シーン中の物体に当たらなかった場合レイが環境マップにヒットしたと考えられます。
そのときの寄与は次のように計算されます。
\begin{eqnarray*}
\alpha \frac{f_s(\vx, \vomega_i, \vomega_o) \abs{\vec{n}, \vomega_i}}{p_\sigma(\vomega_i)} L_e(-\vomega_i)
\end{eqnarray*}
ここで $ \alpha $ はその時点での経路のウェイト、$ \vec{n} $ は点 $ \vx $ における法線、$ \vomega_o $ は出射方向です。そして $ L_e(-\vomega_i) $ は $ \vomega_i $ に対応する環境マップから取得できる放射輝度です。「パストレーシング実装」に載せた寄与の計算とほぼ同じです。唯一違う点としては $ L_e $ に光源上の位置が含まれていないことですが、これも光源が無限遠にあることによります。無限遠から見れば、シーンのどこからレイが飛んできたとしても実質原点からのレイに等しく、光源上の位置はレイの方向から一意に決定されます。そのため $ L_e $ は方向のみの関数で表されます。
このように単純なパストレーシングの場合は、ほとんど無限を意識することなく環境マップによるIBLを自然に扱うことができます。平行光源は光源の位置がデルタ関数で表されることになるので、単純なパストレーシングではサンプリングすることができません。
無限遠光源をうまく扱うために次のようなモデルを考えてみます。
双方向パストレーシングなどのアルゴリズムでは、光源の放射輝度 $ L_e(\vx, \vomega) $ を放射発散度 $ L_e^{(0)}(\vx) $ と、そこから各方向に放射輝度としてどの程度の割合が向かうかを表す方向成分 $ L_e^{(1)}(\vomega) $ に分けたほうがアルゴリズムをクリアに記述できます。「このページ」では楽に記述するために、便宜的に後者をEDF(Emittance Distibution Function)と呼ぶことにします。一般的に使われている呼称ではないので注意してください。 \begin{equation*} L_e(\vx, \vomega) = L_e^{(0)}(\vx) L_e^{(1)}(\vomega) \end{equation*} 前述の無限遠光源モデルに従えば、球状光源上のある点から発せられた光はシーン中のどこから見ても同じ放射輝度に見えるため、光源上の点から見て少なくともシーンのオブジェクトが可視であるところに関してはEDFの値が一定となります。これを満たす最も簡単なEDFは完全拡散EDFとなり、その値は次のようになります。 \begin{equation*} L_e^{(1)}(\vomega) = \frac{1}{\pi} \hspace{5mm} \mathrm{\Brk{sr^{-1}}} \end{equation*} 環境マップに記録されている値をそのまま放射輝度として扱うためには、放射発散度にEDFをキャンセルする量をかける必要があります。 \begin{equation*} L_e^{(0)}(\vx) = \frac{1}{L_e^{(1)}(\vomega)} L_e(\vx) = \pi L_e(\vx) \hspace{5mm} \mathrm{\Brk{W \cdot m^{-2}}} \end{equation*} ※実装上はEDFの値はただの $ 1 $ でも良いくらいなのですが、EDFはあくまで方向に関する分布のみを表しており、正規化されてないと気持ち悪いので上の値を使いました。
Next Event Estimationなどでは光源面から一点をサンプリングする必要があります。
球面上の位置を球の中心からみた立体角に関するPDF $ p_\sigma(\vomega) $ にそってサンプリングできるとします。もし一様にサンプリングするのであれば $ p_\sigma(\vomega) = 1 \; / \; 4\pi $ (半球の場合は $ 1 \; / \; 2\pi $)となります。環境マップの重点的サンプリングについては、このページ末尾で説明します。立体角に関する確率密度は面積に関する確率密度に次の式にしたがって変換することができます。
\begin{eqnarray}
p_A(\vx') = \frac{\abs{\vomega \cdot \vec{n}'}}{\norm{\vx' - \vx}^2} p_\sigma(\vomega) \hspace{5mm} \mathrm{\Brk{m^{-2}}} \label{eq:spatial_density}
\end{eqnarray}
ここで $ \vx' $ は光源上の点、$ \vec{n}' $ はその法線に対応します。$ \vomega $ はサンプルの方向、$ \vx $ はシーン中の点ですが、無限に大きい球なのでこの式の分数部の分子は $ l \to \infty$ となると $ 1 $ に限りなく近づきます。また分母も実質 $ l^2 $ に等しくなります。つまり極限の値としてこのPDFの値はゼロになってしまいますが、無限大の球面上、つまり無限大の面積の中からサンプリングするのでこれは正しいことです。Next Event Estimationではこのサンプルされた光源上の位置からの寄与を計算する際に、幾何項 $ G $ が一緒にかけられると思いますが、幾何項の分母にも $ l^2 $ が含まれることになるので幸いにして無限大となる部分がキャンセルされます。そのため、プログラムに実装する上では、$ p_\sigma(\vomega) $ に相当する部分だけ保持しておけば良いでしょう。
双方向パストレーシングやフォトンマッピングでは、光源上の点のサンプリングだけに留まらず、光源からのレイを生成する必要があります。
光源上の点から見て可視となる全ての場所に等しい放射輝度をもって光が到達するため、EDFの値は定数値になっています。一様なEDFに見合うPDFもまた一様な値を持つべきと感じるかもしれませんが、シーン中のオブジェクトにヒットしないレイの生成は単純に無駄です。理想的には、サンプル位置から見てオブジェクトがあるところの方向にだけレイを飛ばしたいものですが、シーンは任意の形状をとるため単純にはいきません。そこで、シーンに外接するバウンディングスフィア(半径 $ r_w $)を考え、そのバウンディングスフィアがサンプル点に対して張る立体角中にレイを飛ばします。
半径 $ r_w $ の球体が、球体の中心から距離 $ l $ 離れた点に対して張る立体角(図2参照)は、立体角の公式に基づいて次のように計算されます。 \begin{eqnarray*} \int_0^{2\pi} \int_0^{\theta_{max}} \sin \theta \d\theta \d\phi &=& 2\pi \Brkc{-\cos \theta}_0^{\theta_{max}} \\ &=& 2\pi (1 - \cos \theta_{max}) \\ &=& 2\pi \Prt{1 - \frac{\sqrt{l^2 - r_w^2}}{l}} \end{eqnarray*} 球体上の点では全周囲の半分に球体が見える状態になります。例えて言うなら我々が地球の地面に立っている状態では地平線まで地球が見えています(というか地球が見えているから地平線なんですけど)。この状態を上の式で表すと $ l = r_w $ の状態を表しており、全周囲の半分の立体角 $ 2\pi $ に一致することがわかります。
上記の球体が張る立体角を用いて、立体角中に一様にレイを飛ばす場合のサンプル方向に関する確率密度が次のように表されます。 \begin{eqnarray*} p_\sigma(\vomega) &=& \lim_{l \to \infty} \frac{1}{2\pi \Prtd{1 - \frac{\sqrt{l^2 - r_w^2}}{l}}} \\ &=& \lim_{l \to \infty} \frac{l}{2\pi \Prtc{l - \sqrt{l^2 - r_w^2}}} \\ &=& \lim_{l \to \infty} \frac{l^2 + l \sqrt{l^2 - r_w^2}}{2\pi r_w^2} \\ &=& \lim_{l \to \infty} \frac{l^2}{\pi r_w^2} \hspace{5mm} \Brk{\mathrm{sr^{-1}}} \end{eqnarray*} 極限では分子が $ l^2 $ となり無限大になりますが、バウンディングスフィアの大円の面積に反比例していることがわかります。光源からのレイ生成時にはこの確率密度が計算に含まれますが、位置に関する確率密度\eqref{eq:spatial_density}に含まれる項と無限に関わる部分がキャンセルされて無くなります。実装上持っておくべき値は大円の面積 $ \pi r_w^2 $ となります。
球面上の位置と、そこからの出射方向のサンプリングについて示しましたが、無限が含まれているため、プログラムの実装に関しては少し特殊な処理を行う必要があります。
環境マップのある方向 $ \vomega $ をサンプルする確率密度 $ p_\sigma(\vomega) $ は、テクスチャー座標中の確率密度 $ p_{tc}(u, v) $ と次の関係を持ちます(「確率密度関数の変換」参照)。 \begin{equation*} p_\sigma(\vomega) = \frac{p_{tc}(u, v)}{2\pi^2 \sin \theta} \end{equation*}
経度緯度形式の環境マップは一般的に輝度を各画素に記録しています。それでは輝度に応じた重点的サンプリングをしたい場合、そのまま各画素の値に応じてサンプリングすれば良さそうにも思うのですが、1つ罠があります。例として、全方向一様な輝度の環境マップを考えます。この場合、画像の各画素は全て同じ値になっているので、画素値に応じたサンプリングを行う場合のPDFは $ p_{tc}(u, v) = 1 $ となります。これを上の関係式に代入すると次のようになります。
\begin{equation*}
p_\sigma(\vomega) = \frac{1}{2\pi^2 \sin \theta}
\end{equation*}
全方向一様な輝度の環境マップからの重点的サンプリングをしたいので、確率密度の値としては $ 1 /4\pi $ になってほしいところですが、そうなっていません。この式では極に近いほど確率密度が無限に近づきます。経度緯度画像形式の環境マップでは、画像の上端と下端が極に集中してマッピングされるため、このような結果となります。そのため、環境マップに記録された輝度値に関して正しく重点的サンプリングを行うためには、画素値そのものに応じてサンプリングするのではなく、緯度方向の補正をかけてサンプリングする必要があります。具体的には縦方向のテクスチャー座標 $ v $ に関して $ \sin \pi v $ を画素値にかけた値に応じて重点的サンプリングを行います。
全方向一様な輝度の環境マップに関して正しく重点的サンプリングを行うための、テクスチャー座標中のPDFは次の形で表されます。
\begin{equation*}
p_{tc}(u, v) = \frac{\pi}{2} \sin \pi v
\end{equation*}
これを前述の関係式に代入し、$ \theta = \pi v $ という関係を用いれば実現したい確率密度 $ 1 \;/\; 4\pi $ が得られることがわかります。
\begin{equation*}
p_\sigma(\vomega) = \frac{1}{2\pi^2 \sin \theta} \frac{\pi}{2} \sin \pi v = \frac{1}{4\pi}
\end{equation*}
無限遠光源からのレイトレース時のサンプリング手法として、シーンのバウンディングスフィアの大円に対する一様サンプリングなどを紹介しましたが、もっと効率的なサンプリングを行う手法[Bashford2013]が提案されています。しかしこのページで解説した、無限大を含む項のキャンセルのされ方などといった考え方は同様に通用すると思います。