Physics and Math of Shading (3)
こないだ の続き。
Implementing Physical Shading Models for Film and Game Production
これまでに紹介した BRDF に、よく使われる光源モデルを適用する方法を考える。
General Lighting
たいていの場合、BRDF は(スカイライト や相互反射などを含めた)全方向からの入射光を積分して考える。これを真面目に得には大域照明 global illumination が必要だが、詳細は割愛する。
Image-Based Lighting
離れた光源からの入射光を環境マップ environment maps に保存して使う方法を Image-Based Lighting という。GPU のインターポレータやバンプマッピングの影響で法線が裏返ったとき絵が崩れるけど、そういうときは N・L の内積を 0 にクランプするよりも、絶対値をとったほうがフレネルの計算結果(N・L の影響が大きい)が落ち着いていい結果になりやすい。
環境マップのノイズを減らすには、重点的サンプリング importance sampling を使うといい。ゲーム制作向けには、近似的手法である プレフィルタリング も便利だ。
環境マップは理論的には 凸包 convex への入射を計算するものだが、実際には非凸包に対して適用されることもある。そういうときは、自己遮蔽 self-occlude はひとまず無視して、AO 等の近似手法を用いられる。また、異なる入射位置でサンプリングしたような理論的に正しくない環境マップを利用したりもするが、全体での色味と光の強ささえ正しければ、意外とバレない。
Area Light Sources
太陽のように強さと大きさの両方を持つ光源の場合、理論的には環境マップに含まれるのが正しい。ただ実際には、影を計算したり光源の調整をする都合上、環境マップとは別々にするほうが扱いやすい。また、ここでも重点的サンプリング(やその近似手法)が効果を発揮する。
Punctual Light Sources
エリアライトは、(ポイントライトやディレクショナルライトなどの)現実ではありえない光源 punctual light sources で近似されることが多い。物理的に正しいわけではないが、高くない計算負荷でそれなりに見栄えのする絵がつくれるからだ。
これらの光源で使われる「ライトカラー c_{light}」というのを、「真っ白なランバート面に、正面からからまっすぐ光を当てたときの面の色」と考えることにする。この光源の照射角をεとすると、ラディアンス L_{tiny}(l) は以下のように定義できる。
式(8)は、角度εの外側には光が照射されないということを意味する。式(9)は、「真っ白なランバート面に~」というライトカラーの定義を数式で表したものだ。
ラディアンスとは微小角あたりの入射光量なので、ε=0 の極限を考える。このとき、ライトカラーの定義より内積 N・L は 1 に収束する(N と L が並行になる)ので、以下の式を得る。
これを BRDF の式に代入すると、最終的な計算式は式(14)になる。
BRDF 本来の式と比べるとだいぶ簡略化され、計算負荷も低くなった。実際のゲームでは N・L を 0 にクランプして、ポリゴンの裏面にライトが当たらないようにすることも多い。また、現実世界では光の量は距離の2乗に比例して減衰するが、計算負荷や絵作りの都合上、他の減衰方法を使うこともある。
相互反射を行うときにこの計算をそのまま適用するのはよくない。相互反射時の複雑な入射を考慮していないため、特にスペキュラの強い表面などで見栄えが悪くなりがちだ。そういうときは、前述の IBL (Image-Based Lighting) や、後述の環境光 Ambient Lighting を使う。
Ambient Lighting
環境光は低周波の(位置によって入射光があまり変化しないような)光を表現するのに使われるものだ。計算結果に定数を上乗せするだけの単純な方法から、球面調和関数 spherical harmonics を使う複雑な方法まで様々ある。大抵はディフューズ BRDF にだけ適用され、スペキュラ BRDF にはもっと高周波な IBL を使ったりすることが多い。ただ、IBL をスペキュラに適用する方法もゲーム業界内でいろいろ研究されてはいる。