この資料では 物理ベースレンダリング(Physically Based Rendering) を実現するために必要な数学・理論・実装について説明しています。
次のような事柄をこの資料では説明しています。
- レイトレの数学的モデル
- 光の物理量
- BSDF(BRDF, BTDF)
- レンダリング方程式
- レンダリング方程式の作用素表現
- カメラのモデル化
- 経路積分形式のレンダリング方程式
- レンダリング方程式の計算について
レイトレの数学的モデル
まずレイトレーシングで行っていることを数学的に表現することを考えます。
方向
方向ベクトルωは3次元の単位球面S2={∣∣v∣∣=1∣v∈R3}上の点として表現します。こうすることで方向ベクトルは大きさが1に正規化されたもののみになります。
物体表面
シーンにある物体表面上の点全体を表す集合をMとします。物体表面上で微積分が行えないと理論が展開できないので、Mは 区分的に微分可能な2次元多様体(2-dimensional Piecewise Differencial Manifold) として定義しておきます。
一般の空間上での積分
レイトレでは方向ベクトルによる積分や、物体表面上での積分などが頻繁に出てきます。これらの厳密な定義を知らなくても議論を進めることはできるのですが、ある程度知らないと何故?ってなると思うので、簡単に紹介します。
一般の空間X上での積分を定義するためには、測度(Measure)μ というものを導入し、測度空間(Measure Space)(X,F,μ)を構成する必要があります。
σ加法族
Fは σ加法族 といい、Xの部分集合を持つ集合(集合族)です。σ加法族は次のような定義になっています。
- ϕ∈F
- D∈F⟹Dc∈F
- D1,D2,...∈F⟹∪i=1∞Di∈F
この定義から Fに属する集合の和・差・積を高々加算無限回行って得られる集合はまたFに属している ことが分かります。
このFに属している集合を 可測集合(Measurable Set) といいます。後で見るように測度はFに含まれる集合に対して定義されているので、可測集合でない集合では測度が計算できません。
測度
Fに含まれる集合D1,D2,...∈Fに対して次のような集合関数μを定義します。
- 0≤μ(Di)≤∞ (非負性)
- μ(ϕ)=0
- Di∩Dj=ϕ(i=j)のとき、μ(∪i=1∞Di)=∑i=1∞μ(Di) (可算加法性)
この集合関数を 測度(Measure) といいます。測度は与えられた集合の大きさを測ってくれる関数です。例えばR上なら長さ、R2なら面積が測度の1つになります。
測度による積分
単関数の積分
Fに属し、互いに交わらない集合D1,D2,...,Dnが与えられているとします。D=∪i=1nDiとします。Di上で一定値ai∈Rを取る、D上で定義された関数fを考えます。この関数は集合の定義関数1Di(x)を用いて
f(x)=i=1∑nai1Di(x) x∈D
として表現できます。このような関数fを 単関数(Simple Function) といいます。
ai≥0となる単関数をf≥0で表すことにします。
単関数の積分を考えましょう。リーマン積分では、一変数関数の積分はx軸を一定間隔で分割し、その区間幅と関数の値をかけ合わせたものを足すことで積分を定義していました。
これと同様に、正の単関数f≥0の測度μによる積分を
∫Dfdμ=i=1∑naiμ(Di)
として定義します。(これはDの表し方によらない)
可測関数
D上の一般の関数で上のような積分を定義しようとすると、μ(Di)が計算できる必要があることが分かります。つまり、f(x)=aiであるようなxの集合をf=aiと表すとすると、(f=ai)∈Fである必要があります。
σ加法族の定義から、これは(f<ai)∈Fと同値であることが分かります。これを満たす関数を 可測関数(Measurable Function) といいます。
一般の可測関数の積分
D上の任意の可測関数fの積分を考えます。fを
f+(x)=max{f(x),0} f−(x)=max{−f(x),0}
のように、値が正の部分と負の部分に分割します。このときf+,f−≥0です。
f(x)はこの2つの関数を用いてf(x)=f+(x)−f−(x)と表せます。
fが可測であることは、f+とf−が両方とも可測であることと同値です。
まずf+の積分を考えます。f+に対しては、D上の単関数fi(x)≥0の単調増加列で、fに各点収束するものが存在します。この単調増加列を{fi}としたとき、f+の測度μによる積分を
∫Df+dμ=i→∞lim∫Dfidμ
として定義します(これは{fi}の表し方によらない)。f−の積分も同様に定義されます。
次にfの積分を考えます。f=f+−f−と表されているので、∫Ef+dμと∫Ef−dμのどちらか一方が有限の値を取るとき、fの測度μによる積分を
∫Dfdμ=∫Df+dμ−∫Df−dμ
と定義します。この値が有限のとき、fはD上可積分であるといいます。
S2上での積分
S2上の表面積を表す測度を 立体角測度(Solid Angle Measure) といい、σで表します。
これは平面の角度の概念を3次元空間に一般化したようなものです。Ω∈S2上の可測関数fの立体角測度による積分を
∫Ωf(ω)dσ(ω)
と表します。(多様体論の微分形式からこのような測度が導かれるようです)
具体的な計算方法
この積分は半径1の球面座標系(θ,ϕ)を用いて表すことができます。立体角と球面座標系には
dσ=sinθdθdϕ
という関係があります。((x,y,z)→(r,θ,ϕ)のヤコビアンを求めてr=1と置くとsinθが得られる)
これを用いて立体角による積分はΩを区間[θ1,θ2]×[ϕ1,ϕ2]として表現することで
∫Ωf(ω)dσ(ω)=∫ϕ1ϕ2∫θ1θ2f(θ,ϕ)sinθdθdϕ
と計算することができます。これは後で頻繁に使います。
M上での積分
M上の表面積を表す測度を 面積測度(Area Measure) といい、Aで表します。
D∈M上の可測関数fの面積測度による積分を
∫Df(x)dA(x)
と表します。(これも立体角測度と同様に、多様体論からこのような測度が存在することが言えます)
レイ
レイは始点o∈R3と、方向ベクトルd∈S2を定義することで表現できます。レイ上にある全ての点集合Rは
R={o+td∣t∈R+}
と表現できます。ここでR+は正の実数全体を表す集合です。
レイキャスト関数
シーンMが与えられたとき、レイを飛ばしてMとの衝突点x′を求める関数を レイキャスト関数(Raycasting Function) r(x,d)として定義します。
tcloser(x,d)=inf{t∈R∣t>0,o+td∈M}=o+tclosed
tcloseはoからdにレイを飛ばしたときの衝突距離を表します。
光の物理量
物理ベースレンダリングを行うためには、まず光のどういった物理量を計算すれば良いのかを知らなくてはなりません。物理ベースレンダリングでは 放射測定学(Radiometry) と呼ばれる物理の分野で定義される物理量が計算の基礎になります。
光のエネルギー
波長λの光子(Photon) 1つのエネルギーeλは
eλ=λhc
として定義されます。ここでhはプランク定数、cは光速です。
放射エネルギー
波長λの光子がn個あるとき、スペクトル放射エネルギーQλは
Qλ=neλ
として定義されます。これを全波長に渡って積分することで、光の放射エネルギーQが
Q=∫0∞Qλdλ
として定義されます。これはそれぞれの波長で存在する光子の数を合計したものと見ることができます。
放射束
放射束(Radiant Flux) Φは単位時間あたりの放射エネルギーで、以下のように定義されます。
Φ=dtdQ
これは単位時間あたりの光子の数を表していると見ることができます。
放射照度
放射照度(Irradiance)E はM上の単位面積あたりの放射束を表し、
E(x)=dAdΦ
と定義されます。これはM上のある点xを単位時間あたりに通過する光子の数と見ることができます。
放射輝度
放射輝度(Radiance)LはM上の単位面積あたり、単位立体角あたりの放射束として定義され
L(x,ω)=∣cosθ∣dAdσd2Φ
と表されます。θは点xにおける法線N(x)と方向ベクトルωのなす角度です。∣cosθ∣は
∣cosθ∣=∣N(x)⋅ω∣
として、2つのベクトルの内積をとることで計算できます。∣cosθ∣dAは物体表面上の単位面積dAを方向ベクトルωの方向に投影した単位面積を表しています。
放射輝度はM上のある点xにある方向ωからやってくる、単位時間あたりに通過する光子の数を表していると考えることができます。
物理ベースレンダリングでは放射輝度が最も重要な物理量です。レイトレではカメラセンサー上の点に、ある方向からやってくる光の強さを計算することになりますが、この光の強さというのがまさに放射輝度になっています。
放射輝度の重要な性質として、真空中では光が進行しても放射輝度の値が変化しない ことが挙げられます。真空のシーンでは物体表面上でしか放射輝度の変化が発生しないので、レイが空気中を進行している最中の光の作用を全て無視することができます。
放射輝度から放射照度を求める
放射輝度L(x,ω)に∣cosθ∣をかけたものを立体角測度で積分することで放射照度が求まります。
E(x)=∫ΩL(x,ω)∣cosθ∣dσ(ω)
放射輝度から放射束を求める
上で求めたEをさらに面積測度で積分することで放射束が求まります。
Φ=∫DE(x)dA(x)=∫D∫ΩL(x,ω)∣cosθ∣dσ(ω)dA
BRDF
光が物体に当たると反射・屈折が発生します。
点xから方向ωに出射していく放射輝度をLo(x,ω)、点xに方向ωから入射してくる放射輝度をLi(x,ω)と表すことにします。
BRDF(Bidirectional Reflectance Distribution Function - 双方向反射率分布関数) は物体表面上のある点xにおける、光の入射方向ωiと反射方向ωoが与えられたときの反射率を表す関数fで、次のように定義されます。
f(x,ωi,ωo)=dEi(x)dLo(x,ωo)=Li(x,ωi)∣cosθ∣dσ(ωi)dLo(x,ωi)
BRDFは入射してくる単位放射照度あたりの、反射される放射輝度の値を表しています。
このような定義になっているのは、実験結果からEi(x)∝Lo(x,ωo)という関係が知られているためです。
光の入射と反射方向は通常物体表面より上側に限られるため、ωi,ωoは半球面Ω={ω∣N(x)⋅ω≥0,ω∈S2}に属しています。
BRDFがエネルギー保存の法則を満たすために
∫Ωf(x,ωi,ωo)∣cosθ∣dσ(ωi)≤1
となります。また、入射と反射の方向を入れ替えても同じなので
f(x,ωi,ωo)=f(x,ωo,ωi)
という関係があります。
fを指定することで、様々な反射特性を表現することができます。
拡散反射のBRDF
拡散反射(Diffuse Reflection) では光がすべての方向に一様に反射します。
これはBRDFの値が一定であることを意味しており、拡散反射のBRDFは一定の反射率をρとして
f(x,ωi,ωo)=πρ
と表されます。(πが出てくるのはエネルギー保存則を満たすため)
完全鏡面のBRDF
完全鏡面の場合、入射した光は必ず一意の反射方向に反射するので、デルタ関数δ(ωi,ωo)を用いて
f(x,ωi,ωo)=ρ∣cosθ∣δ(ωi,ωo)
と表されます。
反射方程式
入射してくる放射輝度Li(x,ωi)とBRDFが与えられている時、反射する放射輝度Lo(x,ωo)の値を計算してみましょう。
BRDFの定義から
dLo(x,ωo)=f(x,ωi,ωo)Li(x,ωi)∣cosθ∣dσ(ωi)
両辺を立体角測度に関して全領域(半球面Ω)で積分することで
Lo(x,ωo)=∫Ωf(x,ωi,ωo)Li(x,ωi)∣cosθ∣dσ(ωi)
この方程式を 反射方程式(Reflection Equation) といいます。
レンダリング方程式
物体が点xで発光し、方向ωoに放射している放射輝度の値をLe(x,ωo)で表すことにします。すると反射方程式と組み合わせることで、xからωoに反射する放射輝度の値は
Lo(x,ωo)=Le(x,ωo)+∫Ωf(x,ωi,ωo)Li(x,ωi)∣cosθ∣dσ(ωi)
として表されます。この方程式を レンダリング方程式(The Rendering Equation) といいます。(他にも光輸送方程式(LTE - Light Transport Equation)などの名前があります)
右辺第一項は発光を表しているので発光項、右辺第二項は反射を表しているので反射項と呼ばれます。
レンダリング方程式の重要性
レンダリング方程式は物理ベースレンダリングで最も重要な基礎方程式になっています。画像を生成するためにはカメラセンサー上の点xに、ある方向ωiからやってくる放射輝度の値Li(x,ωi)を知る必要があるのですが、この値をレンダリング方程式を用いて計算することができます。
つまり、物理ベースレンダリングとはレンダリング方程式を計算することに帰着されます。世の中には物理ベースレンダリングを達成するための様々なアルゴリズムが存在しますが、それらは全てこのレンダリング方程式をいかにして計算するかということを工夫したものです。
レンダリング方程式の計算
この方程式を計算するためにはLeの値、BRDFの値、そしてLiを知っている必要があります。LeとBRDFはシーンを作った時点で既知ですが、Liは未知なので計算する必要があります。
Li(x,ωi)を計算するには再びレンダリング方程式を適用することができます。x′=r(x,ωi)とすると、Li(x,ωi)=Lo(x′,−ωi)なので
Li(x,ωi)=Lo(x′,−ωi)=Le(x′,ωi′)+∫Ωf(x′,ωi′,−ωi)Li(x′,ωi′)∣cosθ∣dσ(ωi′)
として、Li(x,ωi)が計算できます。
ここでLi(x′,ωi′)の計算に再びレンダリング方程式を適用します。このように再帰的にレンダリング方程式を使うことで、Lo(x,ωo)を計算することができます。これを理論的にきれいな形としてまとめたのが次の内容です。
レンダリング方程式の作用素表現
レンダリング方程式は再帰的な方程式になっていますが、これを関数解析で出てくる線形作用素を使用することで、簡単な代数方程式として表現することができます。
ここでは放射輝度の関数空間Lを考えます。この空間上で定義される線形写像F:L→Lを線形作用素(Linear Operator) といいます。線形作用素は関数を別の関数に移す線形写像です。身近な例としては微分・積分が線形作用素の1つになっています。
局所散乱作用素
レンダリング方程式の再帰をきれいな形として書くために、次のような局所散乱作用素(Local Scattering Operator)Sを定義します。
Sh(x,ωo)=∫Ωf(x,ωi,ωo)h(x,ωi)∣cosθ∣dσ(ωi)
局所散乱作用素Sを使用することで、ある点の入射放射輝度Liが与えられているときに、その点で反射される放射輝度Loを
として表現できます。
進行作用素
さらに放射輝度の真空中の伝播を表すために、進行作用素Gを定義します。
Gh(x,ωi)=h(r(x,ωi),−ωi)
進行作用素Gを利用することで、ある点から出射した放射輝度Loが別の点に入射するとき、その点における入射放射輝度Liを
として表現できます。
レンダリング方程式の作用素表現
局所散乱作用素Sと進行作用素Gを組み合わせることで、レンダリング方程式を
Lo=Le+SGLo
として表現することができます。ここでさらにT=SGを光輸送作用素として定義すれば
Lo=Le+TLo
となります。これを レンダリング方程式の作用素表現 といいます。これは放射輝度の関数空間上で成り立つ代数的関係を表しています。
レンダリング方程式のノイマン級数展開
作用素表現のレンダリング方程式
Lo=Le+TLo
は単純な代数方程式になっています。この方程式は関数方程式ですが、関数のあらゆる引数に対してこの関係が成り立っているので、シーン中の放射輝度の均衡関係を表していると見ることができます。(光子が光源から発射されて反射を繰り返していくと、シーン中のあらゆる地点で光子の単位時間あたりの通過量が一定になる)
これを変形することでレンダリング方程式の解を明示的に表現することが可能です。
右辺のTLoを左辺に移行することで
Lo−TLo(I−T)Lo=Le=Le
ここでIは恒等作用素であり、Ih=hです。
(I−T)の逆作用素(I−T)−1を用いることで
Lo=(I−T)−1Le
と書くことができます(逆作用素はBRDFがエネルギー保存の法則を満たすなら存在することが示されます)。右辺にはLeしかないので、これがレンダリング方程式の明示的な解になっています。
(I−T)−1はノイマン級数展開することが可能で
(I−T)−1=I+T+T2+T3+⋯
と表されます。したがってレンダリング方程式は
Lo=Le+TLe+T2Le+T3Le+⋯
と表現されます。これは レンダリング方程式のノイマン級数展開 と呼ばれます。この形では、出射放射輝度を求めるためには、シーン中の発光放射輝度を0回、1回、2回、⋯, ∞回反射させたものを足し合わせれば良いということを言っています。
カメラのモデル化
光の伝達はレンダリング方程式としてモデル化することができました。次にカメラをモデル化することを考えてみます。
カメラはセンサー上に大量の画素を持ち、画素1つ1つが入射してくる光子の数を記録することによって光の強さを記録しています。これはつまり、非常に短い時間では放射束を記録しているということです。
カメラは入射してくる光をセンサー上に結像させるためにレンズを前面に持っています。レンズは一般的に複数枚の凹凸レンズを組み合わせて構成されます。
カメラからレイを出射することを考えます。物理的にはセンサーからレイが出発して、多くのレンズで屈折を繰り返してからシーンに出ていくようにモデル化した方が良いですが、ここでは話をシンプルにするために、途中の屈折過程はブラックボックス化し、レンズ最前面からいきなりレイが出射すると考えます。(画素の範囲外に出るレイを除けば画素上から出るレイと1対1対応する)
j番目の画素が記録する光の強さIjを考えます。レンズ最前面上の点をx∈D、ここから出るレイの方向をωとします。このレイに対応する画素のセンサー感度をWe(j)(x,ω)(これはMeasure Contribution Functionと呼ばれる)、レンズ最前面にレイの方向から入射してくる放射輝度をLi(x,ω)とします。するとθをxにおける法線ベクトルとωのなす角として
Ij=∫D∫S2We(x,ω)Li(x,ω)∣cosθ∣dσ(ω)dA(x)
となります。
Weの関数形を変えることで、様々なカメラを表現することが可能です。
ピンホールカメラ
ピンホールカメラの場合、ピンホールの位置をxpとして、D={xp}です。また画素jに対応してレイの出射方向が一意に定まるため、Weはデルタ関数で表現されることになります。したがってIjを計算する式は積分をはずせて
Ij=We(x,ω)Li(x,ω)∣cosθ∣
のように簡略化されます。
経路積分形式のレンダリング方程式
レンダリング方程式は方向に関する積分方程式として表されていましたが、これを光の経路(x0,x1,⋯,xk)に関する積分として表現することも可能です。ここではそのような表現について見ていきます。
ある点xから別の点x′に向かう方向ベクトルをx→x′として表すことにします。
立体角測度と面積測度の関係
物体表面上の点x′における微小単位面積dAを点xに置かれた単位球面上に投影することを考えます。すると
dσ(ω)=V(x,x′)∣∣x′−x∣∣2∣cosθ′∣dA(x′)
という関係があることが分かります。ここでcosθ′=N(x′)⋅(x′→x)です。V(x,x′)は 可視関数(Visible Function) と呼ばれ、xとx′がお互いに見えるときに1、それ以外のときに0をとる関数です。
この関係式を用いて立体角測度と面積測度に関する積分を互いに積分変数変換することが可能になります。
3点形式のレンダリング方程式
ある点x1からレンズ上の点x0に出射する放射輝度Lo(x1→x0)を考えます。レンダリング方程式を立体角測度に関する積分から面積測度に関する積分に積分変数変換することによって、
Lo(x1→x0)=Le(x1→x0)+∫Mf(x0→x1→x2)Li(x1→x2)V(x1,x2)G(x1,x2)dA(x2)
と書くことができます。
G(x1,x2)は 幾何項(Geometry Term) と呼ばれ、積分変換変換による項と∣cosθ∣をかけたもので
G(x1,x2)=∣∣x2−x1∣∣2∣cosθ∣∣cosθ′∣
と表されます。
このように視点x0, 注目点x1, 反射方向の点x2を用いた形のレンダリング方程式を 3点形式のレンダリング方程式 といいます。
経路積分形式のレンダリング方程式
3点形式のレンダリング方程式をノイマン級数展開することで、次のような経路積分形式のレンダリング方程式が得られます。
Lo(x1→x0)=Le(x1→x0)+∫Mf(x0→x1→x2)V(x1,x2)G(x1,x2)Le(x2→x1)dA(x2)+∫M∫Mf(x0→x1→x2)f(x1→x2→x3)V(x1,x2)V(x2,x3)G(x1,x2)G(x2,x3)Le(x3→x2)dA(x2)dA(x3)+⋯
カメラモデルの導入
カメラモデルの式
Ij=∫D∫S2We(x0,ω)Li(x0,ω)∣cosθ∣dσ(ω)dA(x0)
を経路積分形式のレンダリング方程式に組み込むことを考えます。立体角測度による積分を面積測度による積分に変換することで
Ij=∫D∫S2We(x0,ω)Li(x0,ω)∣cosθ∣dσ(ω)dA(x0)=∫M∫DWe(x0→x1)V(x0,x1)G(x0,x1)Li(x0→x1)dA(x0)dA(x1)=∫M∫MWe(x0→x1)V(x0,x1)G(x0,x1)Li(x0→x1)dA(x0)dA(x1)
となります。(DをMに変えていることに注意。このようにしてもWeをD以外の点で0にすることで値は変化しない)
Li(x0→x1)=Lo(x1→x0)なので、経路積分形式のレンダリング方程式を代入することで
Ij=k=1∑∞k+1∫M⋯∫MWe(x0→x1)i=1∏k{f(xi−2→xi−1→xi)V(xi−1,xi)G(xi−1,xi)}Le(xk→xk−1)dA(x0)dA(x1)⋯dA(xk)
のように書けます。ここでf(x−1→x0→x1)=1としています。
xkˉ=(x0,x1,⋯,xk)とおきます。これを長さk+1の光の 経路(Path) と呼びます。
Tk(xkˉ)=∏i=1k{f(xi−2→xi−1→xi)V(xi−1,xi)G(xi−1,xi)}を スループット(Throughput) として定義すると
Ij=k=1∑∞k+1∫M⋯∫MWe(x0→x1)Tk(xkˉ)Le(xk→xk−1)dA(x0)dA(x1)⋯dA(xk)
のようになります。これが 経路積分形式(Path Integral Form) と呼ばれるレンダリング方程式の形です。
レンダリング方程式の計算について
再帰的な形のレンダリング方程式を経路積分形式で表現することで、レンダリング方程式はn次積分の無限級数になっていることが分かりました。数値積分を利用すればこれは数値計算が可能な形になっています。
しかし、10回の反射を経た光は10次元の積分、100回の反射を経た光は100次元の積分、⋯というように、高次元の積分を数値的に計算する必要があります。
高次元の積分は通常の数値積分の手法だと計算量が爆発的に多くなります。例えばそれぞれの軸を10個のサンプル点に分割する場合、100次元積分を計算しようとすると10100のサンプル点を生成することになります。これは現代のコンピューターを持ってしても計算が不可能な値です。
これを解決するための手法として、確率論的に積分の値を求める モンテカルロ積分(Montecarlo Integration) というものがあります。レイトレではモンテカルロ積分を用いてレンダリング方程式を解くことが一般的です。