1. はじめに
PBR の式が並んだページは、読む前から少し身構えてしまう。記号が何を指しているかは分かっても、それが画面の明るさにどうつながるのかが、式だけでは掴みにくい。
Math as Code(https://mathasacode.aulenor.com/)の作例の章には、ランバート反射の例がある。ここでは、その作例の数をそのまま追ってみる。式が何を言っているかではなく、数を入れたら何が出てくるか、という順番で見ていく。
2. 式のかたち
作例で使われているランバート反射の BRDF は、次の形だ。
f_r = R / π
R は反射率(reflectance)、f_r は BRDF。見る方向は、この式の中には出てこない。反射率を π で割ったものが、そのまま反射の割合になる。
放射照度(irradiance)の積分と組み合わせると、反射した放射輝度は f_r に光の量を掛けたものになる。作例では、光が面に届く量は、ビームの放射照度に、面の法線と光の方向のなす角の余弦を掛けて求めている。
面(横線)と法線(上向きの矢印)、光の筋。法線と光の筋のなす角が θ で、作例では cosθ = 0.5。
3. コードに翻訳する
作例のコードは、サイトに次の形で載っている。
var { lambertianReflection } = require('./examples/notation.cjs')
var reflectance = 0.5
var beamIrradiance = 2 * Math.PI // W/m² on a plane perpendicular to the beam
var normal = [0, 0, 1]
var lightDirection = [0, Math.sqrt(3), 1] // helper normalizes both vectors
lambertianReflection(reflectance, beamIrradiance, normal, lightDirection)
//=> approximately 0.5 W/(m² sr)
ヘルパーが両方のベクトルを正規化する。正規化した光の方向の z 成分は 0.5 なので、余弦は 0.5 になり、出力は (0.5 / Math.PI) * (2 * Math.PI) * 0.5、約 0.5 W/(m² sr) になる。式の上では π が出てきて消えるだけの話だが、数を入れると、どこで何が消えたかが目で追える。
4. 数を追ってみる
作例の入力を、ひとつずつ確認する。
| 項目 | 値 |
|---|---|
| 反射率 R | 0.5 |
| ビームの放射照度 | 2π |
| 面の法線 | [0, 0, 1] |
| 光の方向 | [0, √3, 1] |
| cosθ | 0.5 |
| 反射した放射輝度 | 約 0.5 W/(m² sr) |
光の方向 [0, √3, 1] の長さは √(0 + 3 + 1) = 2。法線 [0, 0, 1] との内積は 1 なので、内積を長さで割ると 1 / 2 = 0.5 になる。この 0.5 が、光が斜めから届いている分の割合だ。
5. 練習カードで、別の数を入れてみる
同じ章の練習カード「Try it: Turn a beam into reflected radiance」には、デフォルトの入力が表示されている。
| 項目 | デフォルト表示 |
|---|---|
| Reflectance R | 0.5 |
| Beam irradiance E⊥ | 6.283185307179586 |
| Surface normal | [0, 0, 1] |
| Direction toward light | [0, 1, 1] |
| Result | 0.707106781187 W/(m² sr) |
6.283185307179586 は 2π の値だ。方向 [0, 1, 1] から出てくる余弦の係数は 1/√2 ≈ 0.7071 で、結果の 0.707106781187 と同じ数になる。作例の 0.5 とは光の向きだけが違うのに、結果が 0.5 から 0.7071 に変わる。変わったのは、光の向きだけだ。
入力を変えると表示がその場で再計算されることも、ライブ確認で確かめた。Reflectance R を 0.5 から 0.8 に変えるだけで、結果は 1.1313708499 W/(m² sr) に変わり、0.5 に戻すと 0.707106781187 に戻った。
6. みなさんに聞きたいこと
ランバート反射の式を初めて見たとき、どこで止まりましたか。f_r = R / π の π で止まった方もいれば、法線と光の内積のところで止まった方もいると思います。次に数式からコードへ翻訳してほしいトピックがあれば、教えてください。
