光の散乱
この節ではプログラムを書かずに、次節で行うライティング処理の大きな変更に向けて用語や概念を説明する。
アルベド
これまでに作ったプログラムは物体表面やボリュームでレイを散乱させていた。これは光と物体表面の間の相互作用を説明するのによく使われるモデルであり、確率を使って自然に実装できる。これまでのプログラムにはライトが吸収されるかどうかを判断する確率がある:
- 光が散乱する確率: \(A\)
- 光が吸収される確率: \(1 - A\)
この \(A\) をアルベド (albedo) と呼ぶ (albedo はラテン語で「白さ」を意味する)。アルベドは分野によっては正確な定義を持つ専門用語だが、どの場合でも何らかの反射率 (reflectance) を表している。アルベド (反射率) は光の色と入射方向によって変化する: 第一巻でガラスを実装したときには、シュリックの近似を使って反射率を計算した。
散乱
多くの物理ベースレンダラでは、光の色を表すのに RGB ではなく複数の波長の集まりが使われる。長い波長の光、中くらいの波長の光、短い波長の光を特定の割合で組み合わせたものが R, G, B だとみなせば、今のプログラムでも同じように考えることができる。
光が散乱するとき、散乱レイの方向の分布は立体角を引数に取る PDF として表せる。この分布をこれから散乱 PDF (scattering PDF) と呼び、\(s(\text{direction})\) と表す。散乱 PDF は入射するレイの入射角 (incident direction) によっても変化する。入射方向による散乱 PDF の変化は、水面から反射する光を見るとよく分かる ──遠くを見て視点の角度 (入射角) が水平に近づくと、水面は鏡のように見える1。
以上の記号を使えば、物体表面の色は次のように表せる2: \[ \text{Color} = \int A \cdot s(\text{direction}) \cdot \text{color}(\text{direction}) \] \(A\) と \(s(\text{direction})\) は視点の方向および散乱位置 (物体表面またはボリューム内部における位置) に依存するので、出力の色はこの二つの値によって変化する。
散乱 PDF
モンテカルロ積分の基礎公式に当てはめると、次の統計的推定値が得られる: \[ \text{Color} = \frac{A \cdot s(\text{direction}) \cdot \text{color}(\text{direction})}{p(\text{direction})} \] ここで \(p(\text{direction})\) は "ランダム" に生成した方向 \(\text{direction}\) の PDF である。
これまでランバート表面では \(p(\text{direction})\) がコサイン密度となる特別な場合として暗黙の内にこの式を実装していた。\(\theta\) を物体表面の法線と散乱レイの角度とすると、ランバート表面では \(s(\text{direction})\) が \(\cos \theta\) に比例する。PDF の積分は \(1\) になる必要があることを思い出そう。\(\cos \theta \lt 0\) のときは \(s(\text{direction}) = 0\) であり、半球に関する \(\cos \theta\) の積分は次に示すように \(\pi\) となる。
積分を求めるには、球面座標で成り立つ次の等式を使う3: \[ dA = \sin \theta\, d\theta d\phi \] ここから \[ \cos \theta \text{ の単位半球上に渡る面積分} = \int_{0}^{2 \pi} \int_{0}^{\pi / 2} \cos \theta \sin \theta\, d\theta d\phi = 2 \pi \frac{1}{2} = \pi \] を得る。つまりランバート表面における散乱 PDF は \[ s(\text{direction}) = \frac{\cos \theta}{\pi} \] である。
散乱 PDF と等しい PDF を使ってサンプルを行うとすれば \[ p(\text{direction}) = s(\text{direction}) = \frac{\cos \theta}{\pi} \] であり、分母と分子が打ち消し合う。そして \[ \text{Color} = A \cdot \text{color}(\text{direction}) \] が得られる。これは最初に実装した ray_color()
関数にあった式そのものだ! ただここでは、値の大きい方向 (例えばライト方向) へ多くのレイを飛ばせるようこの議論を一般化する必要がある。
以上の議論は標準的ではない。物体表面とボリュームの両方に適用できる数式が欲しかったのでこの議論を使った。他のやり方だと複雑なコードが生まれてしまう。
レイトレーシングに関する標準的な文献では、反射は双方向反射率分布関数 (bidirectional reflectance distribution function, BRDF) によって記述される。この関数は本書の記号を使って簡単に表せる: \[ \text{BRDF} = \frac{A \cdot s(\text{direction})}{\cos\theta} \]
例えばランバート表面では \(\text{BRDF} = A / \pi\) となる。本書で使う記号と \(\text{BRDF}\) の変換は難しくない。
関与媒質 (ボリューム) を考えるときにはアルベドを散乱アルベド (scattering albedo) と呼び、散乱 PDF を位相関数 (phase function) と呼ぶことが多い。