この記事はレイトレアドベントカレンダー2021 24日目の記事です。この記事ではモンテカルロレイトレーシングを用いた一様媒質のボリュームレンダリングの理論的な部分について解説しています。
TL;DR
ボリュームレンダリング方程式をモンテカルロ積分する
指数分布を用いて自由行程サンプリングを行う
ロシアンルーレットによって吸収/散乱イベントの選択を行う
位相関数を用いて散乱方向のサンプリングを行う
一様媒質のレンダリングとは
一様媒質(Homogeneous Medium) とは媒質中で吸収係数(Absorption Coefficient) /散乱係数(Scattering coefficient) が一定となっている媒質のことを言います。水や空気などは一様媒質に近い媒質です。レンダリングでは人間の皮膚もよく一様媒質としてモデル化されます。
媒質中では光は吸収/散乱を繰り返します。それぞれの強さは吸収係数/散乱係数で制御されます。吸収を強くすると媒質の見た目は暗くなり、散乱を強くすると光がボヤけて柔らかい印象が得られるようになります。
以下の画像は一様媒質のレンダリングの例です。手前側が一様媒質でモデル化された物体、奥側が媒質を考慮せずに、表面だけLambert BRDFでモデル化した物体です。
一様媒質のレンダリングの例
一様媒質を考慮した物体では光が滲んで柔らかい印象になっていることが分かると思います。これは媒質中で光が散乱を繰り返して拡散するためです。
特に、物体の後ろ側に光源がある場合は一様媒質のモデルでは光が媒質中を透過するため、物体の厚さが薄い箇所では光が透けて見えます。一方で媒質を考慮していない物体では光は全く透過しません。
光が透過する例
これらは 表面化散乱(Subsurface scattering) の例になっています。
このような質感を表現するためには ダイポールモデル (Dipole model) のような近似モデルを使うことが多かったですが、最近はこの記事で紹介するようなモンテカルロレイトレーシングによる方法で一様媒質のレンダリングを行うことが増えているようです。特に、モンテカルロレイトレーシングによる表面化散乱の計算は Random walk subsurface scattering と言われたりします。
媒質中ではレイがランダムに動き続ける
モンテカルロレイトレーシングによる一様媒質のレンダリングでは、媒質の中を散乱によってレイがランダムに動き続けます。Random walk subsurface scatteringという名前がついているのはこの様子がRandom walkに見えるからだと思います。
近似モデルは高速にレンダリングが可能ですが、あくまで近似なので見た目は不正確になる場合があります。一方でモンテカルロレイトレーシングによる方法では計算量は多くなりますが、正確な見た目を表現することが出来ます。
BlenderのPrincipled BSDFにもSubsurfaceの選択欄でRandom walkという項目があり、これを選択すれば表面化散乱がモンテカルロレイトレーシングで計算されるようになっています。
BlenderのPrincipled BSDF
こういった表面化散乱以外にも、水や霧のレンダリングに一様媒質を用いることが出来ます。以下はコーネルボックスに霧を充満させてレンダリングした例です。
霧が充満したコーネルボックス
光源の周りが霧による光の散乱によってボヤけた感じになっていることが分かります。
このように一様媒質を考慮したレンダリングを行うとレンダリングの表現力が一気に上がります。
以降ではモンテカルロレイトレーシングを用いて一様媒質のレンダリングを行う方法について見ていきます。
ボリュームレンダリング方程式
まずは何を計算すれば良いのかをはっきりさせます。そのために媒質中での放射輝度の変化を記述するRTEとVREという式について見ていきます。
媒質中での放射輝度の変化は以下の 放射輸送方程式(Radiative transfer equation - RTE) によって記述されます。
L ( x , ω ⃗ ) L(x, \vec{\omega}) L ( x , ω ) : 点x x x において方向ω ⃗ \vec{\omega} ω から来る放射輝度
μ a ( x ) \mu_a(x) μ a ( x ) : 点x x x における吸収係数
μ s ( x ) \mu_s(x) μ s ( x ) : 点x x x における散乱係数
L e ( x , ω ⃗ ) L_e(x, \vec{\omega}) L e ( x , ω ) : 点x x x において方向ω ⃗ \vec{\omega} ω に発光する放射輝度
L s ( x , ω ⃗ ) L_s(x, \vec{\omega}) L s ( x , ω ) : 点x x x において方向ω ⃗ \vec{\omega} ω へ散乱される外から来た放射輝度
( ω ⃗ ⋅ ∇ ) L ( x , ω ⃗ ) = − μ a ( x ) L ( x , ω ⃗ ) − μ s ( x ) L ( x , ω ⃗ ) + μ a ( x ) L e ( x , ω ⃗ ) + μ s ( x ) L s ( x , ω ⃗ ) (1) (\vec{\omega}\cdot \nabla)L(x, \vec{\omega}) = -\mu_a(x)L(x, \vec{\omega}) - \mu_s(x)L(x,\vec{\omega}) + \mu_a(x)L_e(x, \vec{\omega}) + \mu_s(x)L_s(x, \vec{\omega}) \tag{1} ( ω ⋅ ∇ ) L ( x , ω ) = − μ a ( x ) L ( x , ω ) − μ s ( x ) L ( x , ω ) + μ a ( x ) L e ( x , ω ) + μ s ( x ) L s ( x , ω ) ( 1 )
式(1)の概念図
この方程式は方向ω ⃗ \vec{\omega} ω に微小距離d s ds d s だけ移動した時、放射輝度がどのように変化するかを表した式です。各項は次のような物理的意味を持っています。
− μ a ( x ) L ( x , ω ⃗ ) -\mu_a(x)L(x, \vec{\omega}) − μ a ( x ) L ( x , ω ) : 吸収による放射輝度の減衰
− μ s ( x ) L ( x , ω ⃗ ) -\mu_s(x)L(x, \vec{\omega}) − μ s ( x ) L ( x , ω ) : 散乱(Out-scattering)による放射輝度の減衰
μ a ( x ) L e ( x , ω ⃗ ) \mu_a(x)L_e(x, \vec{\omega}) μ a ( x ) L e ( x , ω ) : 発光(Emission)による放射輝度の増加
μ s ( x ) L s ( x , ω ⃗ ) \mu_s(x)L_s(x, \vec{\omega}) μ s ( x ) L s ( x , ω ) : 外から入ってきた光の散乱(In-scattering)による放射輝度の増加
吸収係数/散乱係数は本来は波長依存の量ですが、今回は簡単のために波長非依存の量であると仮定して話を進めます。
ここでL s ( x , ω ⃗ ) L_s(x, \vec{\omega}) L s ( x , ω ) は以下のように球面全体での積分で定義されます。
S 2 \mathcal{S^2} S 2 球面全体
f p ( ω ⃗ , ω ⃗ ′ ) f_p(\vec{\omega}, \vec{\omega}') f p ( ω , ω ′ ) : 位相関数
L i ( x , ω ⃗ ′ ) L_i(x, \vec{\omega}') L i ( x , ω ′ ) : 点x x x に方向ω ⃗ ′ \vec{\omega}' ω ′ から入射する放射輝度
L s ( x , ω ⃗ ) = ∫ S 2 f p ( ω ⃗ , ω ⃗ ′ ) L i ( x , ω ⃗ ′ ) d σ ( ω ⃗ ′ ) (2) L_s(x, \vec{\omega}) = \int_{\mathcal{S}^2} f_p(\vec{\omega}, \vec{\omega}')L_i(x, \vec{\omega}')d\sigma(\vec{\omega}') \tag{2} L s ( x , ω ) = ∫ S 2 f p ( ω , ω ′ ) L i ( x , ω ′ ) d σ ( ω ′ ) ( 2 )
式(2)の概念図
この式は媒質中で周辺から入ってきた光が方向ω ⃗ \vec{\omega} ω にどれだけ散乱されるかを表した式です。位相関数f p f_p f p はボリューム版のBRDFのようなものとして見れます。
式(1)はL s L_s L s の項が積分を含んでいるので、積分微分方程式 (Integro-differential equation) になっています。このままでは扱いづらいので、両辺を積分して微分を消すことを考えます。
境界条件として点x x x から距離t t t だけ離れた点x − t ω ⃗ x - t\vec{\omega} x − t ω が媒質の終端にあると仮定すると、距離0 0 0 からt t t まで積分することで以下の式を得ます。
μ t ( x ) = μ a ( x ) + μ s ( x ) \mu_t(x) = \mu_a(x) + \mu_s(x) μ t ( x ) = μ a ( x ) + μ s ( x )
T ( x , x − s ω ⃗ ) = e − ∫ 0 s μ t ( x − s ′ ω ⃗ ) d s ′ T(x, x - s\vec{\omega}) = e^{-\int_0^s \mu_t(x - s'\vec{\omega})ds'} T ( x , x − s ω ) = e − ∫ 0 s μ t ( x − s ′ ω ) d s ′
L ( x , ω ⃗ ) = ∫ 0 t T ( x , x − s ω ⃗ ) ( μ a ( x − s ω ⃗ ) L e ( x − s ω ⃗ , ω ⃗ ) + μ s ( x − s ω ⃗ ) L s ( x − s ω ⃗ , ω ⃗ ) ) d s + T ( x , x − t ω ⃗ ) L ( x − t ω ⃗ , ω ⃗ ) (3) \begin{aligned}
L(x, \vec{\omega}) &= \int_0^t T(x, x - s\vec{\omega})\bigg( \mu_a(x - s\vec{\omega})L_e(x - s\vec{\omega}, \vec{\omega}) + \mu_s(x - s\vec{\omega})L_s(x - s\vec{\omega}, \vec{\omega}) \bigg)ds \\
&+ T(x, x - t\vec{\omega})L(x - t\vec{\omega}, \vec{\omega}) \tag{3}
\end{aligned} L ( x , ω ) = ∫ 0 t T ( x , x − s ω ) ( μ a ( x − s ω ) L e ( x − s ω , ω ) + μ s ( x − s ω ) L s ( x − s ω , ω ) ) d s + T ( x , x − t ω ) L ( x − t ω , ω ) ( 3 )
式(3)の概念図
この式は ボリュームレンダリング方程式(Volume rendering equation - VRE) と呼ばれます。レンダリング方程式のボリューム版です。
第1項の積分は媒質中から得られる放射輝度の合計を表しています。第2項は媒質の終端から入射する放射輝度を表しています。
T ( x , x − s ω ⃗ ) T(x, x - s\vec{\omega}) T ( x , x − s ω ) は 透過率(Transmittance) と呼ばれます。この関数は光が点x − s ω ⃗ x - s\vec{\omega} x − s ω から点x x x まで進んだ時にどれだけ減衰するかを表しています。μ t ( x ) \mu_t(x) μ t ( x ) は 消失係数(Extinction coefficient) と言います。
式(3)はL s L_s L s の項が未知の値L i ( x , ω ⃗ ′ ) L_i(x, \vec{\omega}') L i ( x , ω ′ ) を含んでいますが、この値は再び式(3)を適用することで計算できます。再帰的な展開を繰り返していくとレンダリング方程式と同様に経路積分形式による表現を得ることができます。今回の内容ではそこまでの定式化は必要ないので、ここでは省略します。
ボリュームレンダリングでは式(3)のボリュームレンダリング方程式を数値計算することが目標になります 。
ボリュームレンダリング方程式のモンテカルロ積分
モンテカルロレイトレーシングによるボリュームレンダリングでは式(3)をモンテカルロ積分します。以降ではその方法について見ていきます。
第1項の積分では積分変数として距離s s s があるので、これを確率的にサンプリングすることを考えます。
距離s s s を表す確率変数をS : Ω → [ 0 , ∞ ) S: \Omega \to [0, \infty) S : Ω → [ 0 , ∞ ) とします(Ω \Omega Ω は標本空間)。ここではあえてS S S の値の範囲を[ 0 , ∞ ) [0, \infty) [ 0 , ∞ ) にしています。S ≥ t S \ge t S ≥ t の時は第1項を評価することはできませんが、この時は第2項を評価することにします。つまり距離S S S を用いたロシアンルーレット によって第1項と第2項のどちらを評価するかを確率的に選択します。
この時、式(3)のモンテカルロ積分は以下のように書けます。
p S ( s ) p_S(s) p S ( s ) : 距離S S S の確率密度関数
1 A \mathbb{1}_A 1 A : 指示関数。A A A が成立している時に1、そうでない時に0を返す
P ( S ≥ t ) P(S \ge t) P ( S ≥ t ) : 距離S S S がt t t 以上の値を取る確率
T e r m 1 ( s ) = T ( x , x − s ω ⃗ ) ( μ a ( x − s ω ⃗ ) L e ( x − s ω ⃗ , ω ⃗ ) + μ s ( x − s ω ⃗ ) L s ( x − s ω ⃗ , ω ⃗ ) ) T e r m 2 = T ( x , x − t ω ⃗ ) L ( x − t ω ⃗ , ω ⃗ ) L ^ ( x , ω ⃗ ) = T e r m 1 ( s ) p S ( s ) 1 { s < t } + T e r m 2 P ( S ≥ t ) 1 { s ≥ t } (4) \begin{aligned}
\mathrm{Term1}(s) &= T(x, x - s\vec{\omega})\bigg( \mu_a(x - s\vec{\omega})L_e(x - s\vec{\omega}, \vec{\omega}) + \mu_s(x - s\vec{\omega})L_s(x - s\vec{\omega}, \vec{\omega}) \bigg) \\
\mathrm{Term2} &= T(x, x - t\vec{\omega})L(x - t\vec{\omega}, \vec{\omega}) \\
\widehat{L}(x, \vec{\omega}) &= \frac{\mathrm{Term1}(s)}{p_S(s)}\mathbb{1}_{\{s < t\}} + \frac{\mathrm{Term2}}{P(S \ge t)}\mathbb{1}_{\{s \ge t\}} \tag{4}
\end{aligned} T e r m 1 ( s ) T e r m 2 L ( x , ω ) = T ( x , x − s ω ) ( μ a ( x − s ω ) L e ( x − s ω , ω ) + μ s ( x − s ω ) L s ( x − s ω , ω ) ) = T ( x , x − t ω ) L ( x − t ω , ω ) = p S ( s ) T e r m 1 ( s ) 1 { s < t } + P ( S ≥ t ) T e r m 2 1 { s ≥ t } ( 4 )
これが式(3)の不偏推定量になっていることは以下のように確認できます。
E [ L ^ ( x , ω ⃗ ) ] = ∫ 0 ∞ ( T e r m 1 ( s ) p S ( s ) 1 { s < t } + T e r m 2 P ( S ≥ t ) 1 { s ≥ t } ) p S ( s ) d s = ∫ 0 ∞ T e r m 1 ( s ) p S ( s ) 1 { s < t } p S ( s ) d s + T e r m 2 P ( S ≥ t ) ∫ 0 ∞ 1 { s ≥ t } p S ( s ) d s = ∫ 0 t T e r m 1 ( s ) p S ( s ) p S ( s ) d s + T e r m 2 P ( S ≥ t ) P ( S ≥ t ) = ∫ 0 t T e r m 1 ( s ) d s + T e r m 2 \begin{aligned}
\mathbb{E}[\widehat{L}(x, \vec{\omega})] &= \int_0^{\infty}\bigg(\frac{\mathrm{Term1}(s)}{p_S(s)}\mathbb{1}_{\{s < t\}} + \frac{\mathrm{Term2}}{P(S \ge t)}\mathbb{1}_{\{s \ge t\}}\bigg)p_S(s)ds \\
&= \int_0^{\infty}\frac{\mathrm{Term1}(s)}{p_S(s)}\mathbb{1}_{\{s < t\}}p_S(s)ds + \frac{\mathrm{Term2}}{P(S \ge t)}\int_0^{\infty}\mathbb{1}_{\{s \ge t\}}p_S(s)ds \\
&= \int_0^t\frac{\mathrm{Term1}(s)}{p_S(s)}p_S(s)ds + \frac{\mathrm{Term2}}{P(S \ge t)}P(S \ge t) \\
&= \int_0^t \mathrm{Term1}(s)ds + \mathrm{Term2}
\end{aligned} E [ L ( x , ω ) ] = ∫ 0 ∞ ( p S ( s ) T e r m 1 ( s ) 1 { s < t } + P ( S ≥ t ) T e r m 2 1 { s ≥ t } ) p S ( s ) d s = ∫ 0 ∞ p S ( s ) T e r m 1 ( s ) 1 { s < t } p S ( s ) d s + P ( S ≥ t ) T e r m 2 ∫ 0 ∞ 1 { s ≥ t } p S ( s ) d s = ∫ 0 t p S ( s ) T e r m 1 ( s ) p S ( s ) d s + P ( S ≥ t ) T e r m 2 P ( S ≥ t ) = ∫ 0 t T e r m 1 ( s ) d s + T e r m 2
距離サンプリングを用いた式(4)の計算の物理的意味について考えてみると、距離s s s で媒質中の粒子との衝突が発生し、吸収/散乱が起きたと考えることができます。逆に考えると距離s s s までは粒子との衝突が発生しなかったということです。そのためこのような距離s s s のサンプリングは 自由行程サンプリング(Free-path sampling) と呼ばれます。
自由行程サンプリング
続いてS S S にどのような確率分布を設定するべきかについて考えていきます。
S S S の確率分布の設定
式(4)を見ると、透過率T T T が各項にかかっていることが分かります。S S S の確率分布を透過率T T T に比例させれば重点的サンプリング が行えるので、そのようにします。
S S S の確率密度関数をp S ( s ) p_S(s) p S ( s ) とします。比例定数k k k を用いて以下のようにS S S の確率密度関数を透過率に比例させます。
p S ( s ) = k T ( x , x − s ω ⃗ ) p_S(s) = kT(x, x - s\vec{\omega}) p S ( s ) = k T ( x , x − s ω )
これが確率密度関数になるためには∫ 0 ∞ p S ( s ) d s = 1 \int_0^{\infty} p_S(s)ds = 1 ∫ 0 ∞ p S ( s ) d s = 1 を満たす必要があります。なので、そうなるようにk k k を取ることを考えます。
今考えているのは一様媒質なので、μ t ( x ) \mu_t(x) μ t ( x ) の値は媒質中で一定です。この場合は透過率T T T を以下のように解析的に書くことができます 。
T ( x , x − s ω ⃗ ) = e − ∫ 0 s μ t ( x − s ′ ω ⃗ ) d s ′ = e − ∫ 0 s μ t d s ′ = e − μ t s (5) \begin{aligned}
T(x, x - s\vec{\omega}) &= e^{-\int_0^s \mu_t(x - s'\vec{\omega})ds'} \\
&= e^{-\int_0^s \mu_t ds'} \\
&= e^{-\mu_t s} \tag{5}
\end{aligned} T ( x , x − s ω ) = e − ∫ 0 s μ t ( x − s ′ ω ) d s ′ = e − ∫ 0 s μ t d s ′ = e − μ t s ( 5 )
一様媒質の場合の透過率
式(5)を使って∫ 0 ∞ p S ( s ) d s \int_0^{\infty} p_S(s)ds ∫ 0 ∞ p S ( s ) d s を計算すると以下のようになります。
∫ 0 ∞ p S ( s ) d s = k ∫ 0 ∞ T ( x , x − s ω ⃗ ) d s = k 1 μ t \begin{aligned}
\int_0^{\infty} p_S(s)ds &= k\int_0^{\infty} T(x, x - s\vec{\omega})ds \\
&= k\frac{1}{\mu_t}
\end{aligned} ∫ 0 ∞ p S ( s ) d s = k ∫ 0 ∞ T ( x , x − s ω ) d s = k μ t 1
これが1になれば良いので、k = μ t k = \mu_t k = μ t とすれば良いです。まとめると距離S S S の確率密度関数は以下のようになります。
p S ( s ) = μ t T ( x , x − s ω ⃗ ) = μ t e − μ t s (6) \begin{aligned}
p_S(s) &= \mu_t T(x, x - s\vec{\omega}) \\
&= \mu_t e^{-\mu_t s} \tag{6}
\end{aligned} p S ( s ) = μ t T ( x , x − s ω ) = μ t e − μ t s ( 6 )
これは指数分布 の確率密度関数と同じです。つまりS S S は平均1 μ t \frac{1}{\mu_t} μ t 1 の指数分布に従っています。
これでS S S の確率分布を設定できたので、次はサンプリング方法について見ていきます。
S S S のサンプリング
今回の場合S S S の累積分布関数は解析的に求めることが出来るので、逆関数法 を用いてS S S のサンプリングを行います。
S S S の累積分布関数F S ( s ) F_S(s) F S ( s ) を計算すると以下のようになります。
F S ( s ) = ∫ 0 s p S ( s ) d s = 1 − e − μ t s (7) \begin{aligned}
F_S(s) &= \int_0^s p_S(s)ds \\
&= 1 - e^{-\mu_t s} \tag{7}
\end{aligned} F S ( s ) = ∫ 0 s p S ( s ) d s = 1 − e − μ t s ( 7 )
累積分布関数の逆関数を求めると以下のようになります。
F S − 1 ( u ) = − log ( 1 − u ) μ t F_S^{-1}(u) = -\frac{\log(1 - u)}{\mu_t} F S − 1 ( u ) = − μ t log ( 1 − u )
[ 0 , 1 ] [0, 1] [ 0 , 1 ] の一様乱数をξ \xi ξ として、F S − 1 ( ξ ) F_S^{-1}(\xi) F S − 1 ( ξ ) を計算すれば距離S S S のサンプルs s s を得ることができます。
s = − log ( 1 − ξ ) μ t (8) s = -\frac{\log(1 - \xi)}{\mu_t} \tag{8} s = − μ t log ( 1 − ξ ) ( 8 )
これで重点的サンプリングを用いて距離S S S のサンプルを発生させることが出来るようになりました。実際に式(8)を計算してs s s のサンプルを発生させてみると以下のようになります。
sのヒストグラム
大体指数分布に従っている様子が分かります。
次は式(4)の各項の評価方法について見ていきます。
T e r m 1 \mathrm{Term1} T e r m 1 の評価
T e r m 1 \mathrm{Term1} T e r m 1 は以下のような定義でした。
T e r m 1 ( s ) = T ( x , x − s ω ⃗ ) ( μ a ( x − s ω ⃗ ) L e ( x − s ω ⃗ , ω ⃗ ) + μ s ( x − s ω ⃗ ) L s ( x − s ω ⃗ , ω ⃗ ) ) \mathrm{Term1}(s) = T(x, x - s\vec{\omega})\bigg( \mu_a(x - s\vec{\omega})L_e(x - s\vec{\omega}, \vec{\omega}) + \mu_s(x - s\vec{\omega})L_s(x - s\vec{\omega}, \vec{\omega}) \bigg) T e r m 1 ( s ) = T ( x , x − s ω ) ( μ a ( x − s ω ) L e ( x − s ω , ω ) + μ s ( x − s ω ) L s ( x − s ω , ω ) )
今考えているのは一様媒質なので、μ a \mu_a μ a , μ s \mu_s μ s は定数になります。そのため以下のように書き直しておきます。
T e r m 1 ( s ) = T ( x , x − s ω ⃗ ) ( μ a L e ( x − s ω ⃗ , ω ⃗ ) + μ s L s ( x − s ω ⃗ , ω ⃗ ) ) \mathrm{Term1}(s) = T(x, x - s\vec{\omega})\bigg( \mu_a L_e(x - s\vec{\omega}, \vec{\omega}) + \mu_s L_s(x - s\vec{\omega}, \vec{\omega}) \bigg) T e r m 1 ( s ) = T ( x , x − s ω ) ( μ a L e ( x − s ω , ω ) + μ s L s ( x − s ω , ω ) )
今、距離S S S のサンプリングを行ってs s s が得られているとします。T T T は解析的に書くことができているので、簡単に計算できます。
T ( x , x − s ω ⃗ ) = e − μ t t T(x, x - s\vec{\omega}) = e^{-\mu_t t} T ( x , x − s ω ) = e − μ t t
問題はL e L_e L e とL s L_s L s の項です。これらの項は両方評価しても良いですが、L s L_s L s の評価は再びVREを適用することになるので重いです。そこでロシアンルーレットを行ってL e L_e L e とL s L_s L s のどちらを評価するかを確率的に決めることにします。これをここでは 吸収/散乱イベントサンプリング と呼ぶことにします。吸収イベントが選択されたらL e L_e L e , 散乱イベントが選択されたらL s L_s L s を評価するようにします。
吸収/散乱イベントのサンプリング
吸収イベントを選択する確率をP a P_a P a , 散乱イベントを選択する確率をP s = 1 − P a P_s = 1 - P_a P s = 1 − P a とします。[ 0 , 1 ] [0, 1] [ 0 , 1 ] の一様乱数をξ \xi ξ として、ロシアンルーレットによるT e r m 1 \mathrm{Term1} T e r m 1 の評価は以下のように書けます。
T e r m 1 ^ ( s ) = T ( x , x − s ω ⃗ ) ( μ a L e ( x − s ω ⃗ , ω ⃗ ) P a 1 { ξ < P a } + μ s L s ( x − s ω ⃗ , ω ⃗ ) P s 1 { ξ ≥ P a } ) (9) \widehat{\mathrm{Term1}}(s) = T(x, x - s\vec{\omega})\bigg( \frac{\mu_a L_e(x - s\vec{\omega}, \vec{\omega})}{P_a}\mathbb{1}_{\{\xi < P_a\}} + \frac{\mu_s L_s(x - s\vec{\omega}, \vec{\omega})}{P_s}\mathbb{1}_{\{\xi \ge P_a\}} \bigg) \tag{9} T e r m 1 ( s ) = T ( x , x − s ω ) ( P a μ a L e ( x − s ω , ω ) 1 { ξ < P a } + P s μ s L s ( x − s ω , ω ) 1 { ξ ≥ P a } ) ( 9 )
ここで問題なのはP a P_a P a , P s P_s P s をどのように設定するかです。式を見ると各項にはμ a \mu_a μ a , μ s \mu_s μ s がかかっているため、これを使って重点的サンプリングをすることを考えます。以下のようにP a P_a P a , P s P_s P s を設定すれば良いです。
P a = μ a μ t P s = μ s μ t (10) \begin{aligned}
P_a &= \frac{\mu_a}{\mu_t} \\
P_s &= \frac{\mu_s}{\mu_t} \tag{10}
\end{aligned} P a P s = μ t μ a = μ t μ s ( 1 0 )
μ t = μ a + μ s \mu_t = \mu_a + \mu_s μ t = μ a + μ s だったので、P a P_a P a , P s P_s P s は[ 0 , 1 ] [0, 1] [ 0 , 1 ] の範囲の値を取って確かに確率になっています。
他にもP a P_a P a をμ a L e \mu_a L_e μ a L e の値に比例させるといった設定の仕方があるでしょう。ここでは簡単のために以上の設定のままで考えます。
吸収イベントが選択された場合はT μ a L e P a T\frac{\mu_a L_e}{P_a} T P a μ a L e を評価するだけです。散乱イベントが選択された場合はT μ s L s P s T\frac{\mu_s L_s}{P_s} T P s μ s L s を評価します。
L e L_e L e は簡単に評価できますが、L s L_s L s は積分を計算しなければいけないので厄介です。次はL s L_s L s の計算方法について見ていきます。
L s L_s L s の評価
L s L_s L s は以下のような定義でした。
L s ( x , ω ⃗ ) = ∫ S 2 f p ( ω ⃗ , ω ⃗ ′ ) L i ( x , ω ⃗ ′ ) d σ ( ω ⃗ ′ ) L_s(x, \vec{\omega}) = \int_{\mathcal{S}^2} f_p(\vec{\omega}, \vec{\omega}')L_i(x, \vec{\omega}')d\sigma(\vec{\omega}') L s ( x , ω ) = ∫ S 2 f p ( ω , ω ′ ) L i ( x , ω ′ ) d σ ( ω ′ )
これもモンテカルロ積分で評価することを考えます。 ランダムな方向を表す確率変数をD : Ω → S 2 D: \Omega \to \mathcal{S}^2 D : Ω → S 2 とし、D D D の確率密度関数をp D ( ω ⃗ ) p_{D}(\vec{\omega}) p D ( ω ) とします。D D D から方向ω ⃗ i ′ \vec{\omega}_i' ω i ′ をランダムにN L s N_{L_s} N L s 個生成したとすると、L s L_s L s のモンテカルロ積分は以下のように書けます。
L s ^ ( x , ω ⃗ ) = 1 N L s ∑ i = 1 N L s f p ( ω ⃗ , ω ⃗ i ′ ) L i ( x , ω ⃗ i ′ ) p D ( ω ⃗ i ′ ) (11) \widehat{L_s}(x, \vec{\omega}) = \frac{1}{N_{L_s}}\sum_{i=1}^{N_{L_s}}\frac{f_p(\vec{\omega}, \vec{\omega}_i')L_i(x, \vec{\omega}_i')}{p_D(\vec{\omega}_i')} \tag{11} L s ( x , ω ) = N L s 1 i = 1 ∑ N L s p D ( ω i ′ ) f p ( ω , ω i ′ ) L i ( x , ω i ′ ) ( 1 1 )
重点的サンプリングを考えると、D D D の確率分布はf p f_p f p に比例するように取った方が良いです。ここで位相関数には以下のように全球で積分すると1になる性質があります。
∫ S 2 f p ( ω ⃗ , ω ⃗ ′ ) d σ ( ω ⃗ ′ ) = 1 \int_{\mathcal{S}^2} f_p(\vec{\omega}, \vec{\omega}')d\sigma(\vec{\omega}') = 1 ∫ S 2 f p ( ω , ω ′ ) d σ ( ω ′ ) = 1
つまり、f p f_p f p は比例定数で正規化しなくても、そのまま確率密度関数として使えます。なのでp D ( ω ⃗ ′ ) p_D(\vec{\omega}') p D ( ω ′ ) には位相関数をそのままセットします。
p D ( ω ⃗ ′ ) = f p ( ω ⃗ , ω ⃗ ′ ) p_D(\vec{\omega}') = f_p(\vec{\omega}, \vec{\omega}') p D ( ω ′ ) = f p ( ω , ω ′ )
レンダリングでは位相関数として以下の Henyey-Greenstein phase function がよく使われます。以下HG位相関数と呼ぶことにします。
θ \theta θ : ω ⃗ \vec{\omega} ω とω ⃗ ′ \vec{\omega}' ω ′ のなす角
g g g : 散乱方向を制御するパラメーター
f p ( ω ⃗ , ω ⃗ ′ ) = 1 4 π 1 − g 2 ( 1 + g 2 + 2 g cos θ ) 3 2 f_p(\vec{\omega}, \vec{\omega}') = \frac{1}{4\pi}\frac{1 - g^2}{(1 + g^2 + 2g\cos\theta)^\frac{3}{2}} f p ( ω , ω ′ ) = 4 π 1 ( 1 + g 2 + 2 g cos θ ) 2 3 1 − g 2
g = 0.5の場合のHG位相関数
HG位相関数では逆関数法を用いて位相関数からの方向サンプリングが行えます。ここではそれについては解説しませんが、気になる方は以下のPBRTのページが参考になります。
位相関数を用いて方向ω ⃗ i ′ \vec{\omega}_i' ω i ′ を生成できた後はL i ( x , ω ⃗ i ′ ) L_i(x, \vec{\omega}_i') L i ( x , ω i ′ ) を評価します。この項は媒質中で点x x x に方向ω ⃗ i ′ \vec{\omega}_i' ω i ′ から入射する放射輝度を表しているので、計算にはVREが再び使えます。つまりL i L_i L i を式(4)を用いて再帰的に評価します。
VREの再帰的な適用
式(11)は方向サンプルを複数個取る一般的な場合も含めて記述していますが、実際にはN L s = 1 N_{L_s} = 1 N L s = 1 とします。L s L_s L s の評価は再帰的に行うので、N L s > 1 N_{L_s} > 1 N L s > 1 だと再帰の回数が爆発するためです。以降では以下のようにN L s = 1 N_{L_s} = 1 N L s = 1 として話を進めます。
L s ^ ( x , ω ⃗ ) = f p ( ω ⃗ , ω ⃗ i ′ ) L i ( x , ω ⃗ ′ ) p D ( ω ⃗ i ′ ) (12) \widehat{L_s}(x, \vec{\omega}) = \frac{f_p(\vec{\omega}, \vec{\omega}_i')L_i(x, \vec{\omega}')}{p_D(\vec{\omega}_i')} \tag{12} L s ( x , ω ) = p D ( ω i ′ ) f p ( ω , ω i ′ ) L i ( x , ω ′ ) ( 1 2 )
次は残りのT e r m 2 \mathrm{Term2} T e r m 2 の評価についてです。
T e r m 2 \mathrm{Term2} T e r m 2 の評価
T e r m 2 \mathrm{Term2} T e r m 2 は以下のような定義でした。
T e r m 2 = T ( x , x − t ω ⃗ ) L ( x − t ω ⃗ , ω ⃗ ) \mathrm{Term2} = T(x, x - t\vec{\omega})L(x - t\vec{\omega}, \vec{\omega}) T e r m 2 = T ( x , x − t ω ) L ( x − t ω , ω )
T T T は解析的に書くことができているので簡単に評価できます。
T ( x , x − t ω ⃗ ) = e − μ t t T(x, x - t\vec{\omega}) = e^{-\mu_t t} T ( x , x − t ω ) = e − μ t t
L ( x − t ω ⃗ , ω ⃗ ) L(x - t\vec{\omega}, \vec{\omega}) L ( x − t ω , ω ) は媒質の終端から来る放射輝度を表しているのでした。媒質の終端の隣が別の媒質の場合にはVREを再び適用することができます。つまり、L ( x − t ω ⃗ , ω ⃗ ) L(x - t\vec{\omega}, \vec{\omega}) L ( x − t ω , ω ) を式(4)で再帰的に計算していきます。
媒質の終端が別の媒質の場合
媒質の終端の隣が真空の場合はレンダリング方程式を使ってL ( x − t ω ⃗ , ω ⃗ ) L(x - t\vec{\omega}, \vec{\omega}) L ( x − t ω , ω ) を計算することができます。この場合は通常のパストレーシングを使ってL ( x − t ω ⃗ , ω ⃗ ) L(x - t\vec{\omega}, \vec{\omega}) L ( x − t ω , ω ) を計算すれば良いです。
媒質の終端が真空の場合
アルゴリズムの全体像
これまで説明してきたことをまとめると、一様媒質の場合のVREのモンテカルロ積分は以下のように書けます。
s s s : 距離サンプル
ξ \xi ξ : [ 0 , 1 ] [0, 1] [ 0 , 1 ] の一様乱数
L ^ ( x , ω ⃗ ) = T ( x , x − s ω ⃗ ) ( μ a L e ( x − s ω ⃗ , ω ⃗ ) P a 1 { ξ < P a } + μ s L s ^ ( x − s ω ⃗ , ω ⃗ ) P s 1 { ξ ≥ P a } ) p S ( s ) 1 { s < t } + T ( x , x − t ω ⃗ ) L ( x − t ω ⃗ , ω ⃗ ) P ( S ≥ t ) 1 { s ≥ t } (13) \begin{aligned}
\widehat{L}(x, \vec{\omega}) &= \frac{T(x, x - s\vec{\omega})\bigg( \frac{\mu_a L_e(x - s\vec{\omega}, \vec{\omega})}{P_a}\mathbb{1}_{\{\xi < P_a\}} + \frac{\mu_s\widehat{L_s}(x - s\vec{\omega}, \vec{\omega})}{P_s}\mathbb{1}_{\{\xi \ge P_a\}}\bigg)}{p_S(s)}\mathbb{1}_{\{s < t\}} \\
&+ \frac{T(x, x - t\vec{\omega})L(x - t\vec{\omega}, \vec{\omega})}{P(S \ge t)}\mathbb{1}_{\{s \ge t\}} \tag{13}
\end{aligned} L ( x , ω ) = p S ( s ) T ( x , x − s ω ) ( P a μ a L e ( x − s ω , ω ) 1 { ξ < P a } + P s μ s L s ( x − s ω , ω ) 1 { ξ ≥ P a } ) 1 { s < t } + P ( S ≥ t ) T ( x , x − t ω ) L ( x − t ω , ω ) 1 { s ≥ t } ( 1 3 )
L s ^ ( x − s ω ⃗ , ω ⃗ ) = f p ( ω ⃗ , ω ⃗ ′ ) L i ( x − s ω ⃗ , ω ⃗ ′ ) p D ( ω ⃗ ′ ) (14) \widehat{L_s}(x - s\vec{\omega}, \vec{\omega}) = \frac{f_p(\vec{\omega}, \vec{\omega}')L_i(x - s\vec{\omega}, \vec{\omega}')}{p_D(\vec{\omega}')} \tag{14} L s ( x − s ω , ω ) = p D ( ω ′ ) f p ( ω , ω ′ ) L i ( x − s ω , ω ′ ) ( 1 4 )
T T T やp S p_S p S などは以下のような定義でした。
透過率: T ( x , x − s ω ⃗ ) = e − μ t s T(x, x - s\vec{\omega}) = e^{-\mu_t s} T ( x , x − s ω ) = e − μ t s
距離S S S の確率密度関数: p S ( s ) = μ t T ( x , x − s ω ⃗ ) p_S(s) = \mu_t T(x, x - s\vec{\omega}) p S ( s ) = μ t T ( x , x − s ω )
T e r m 2 \mathrm{Term2} T e r m 2 を評価する確率: P ( S ≥ t ) = 1 − F S ( S < t ) = T ( x , x − t ω ⃗ ) P(S \ge t) = 1 - F_S(S < t) = T(x, x - t\vec{\omega}) P ( S ≥ t ) = 1 − F S ( S < t ) = T ( x , x − t ω )
吸収イベントを選択する確率: P a = μ a μ t P_a = \frac{\mu_a}{\mu_t} P a = μ t μ a
散乱イベントを選択する確率: P s = μ s μ t P_s = \frac{\mu_s}{\mu_t} P s = μ t μ s
散乱方向D D D の確率密度関数: P D ( ω ⃗ ′ ) = f p ( ω ⃗ , ω ⃗ ′ ) P_D(\vec{\omega}') = f_p(\vec{\omega}, \vec{\omega}') P D ( ω ′ ) = f p ( ω , ω ′ )
これらを式(13), 式(14)に代入してあげると以下のようになります。
L ^ ( x , ω ⃗ ) = ( L e ( x − s ω ⃗ , ω ⃗ ) 1 { ξ < P a } + L i ( x − s ω ⃗ , ω ⃗ ′ ) 1 { ξ ≥ P a } ) 1 { s < t } + L ( x − t ω ⃗ , ω ⃗ ) 1 { s ≥ t } (15) \begin{aligned}
\widehat{L}(x, \vec{\omega}) &= \bigg(L_e(x - s\vec{\omega}, \vec{\omega})\mathbb{1}_{\{\xi < P_a\}} + L_i(x - s\vec{\omega}, \vec{\omega}')\mathbb{1}_{\{\xi \ge P_a\}}\bigg)\mathbb{1}_{\{s < t\}} \\
&+ L(x - t\vec{\omega}, \vec{\omega})\mathbb{1}_{\{s \ge t\}} \tag{15}
\end{aligned} L ( x , ω ) = ( L e ( x − s ω , ω ) 1 { ξ < P a } + L i ( x − s ω , ω ′ ) 1 { ξ ≥ P a } ) 1 { s < t } + L ( x − t ω , ω ) 1 { s ≥ t } ( 1 5 )
T T T やp S p_S p S などが消えて、非常にシンプルな形になってくれました。実際に実装する上では式(13), 式(14)を計算するのではなくて、代入して約分した形の式(15)を計算するほうが計算量が少なくて良いでしょう。ただしこの綺麗な形の式が出てくるのはp S p_S p S , P a , P s P_a, P_s P a , P s , p D p_D p D などをそうなるように取ったためです。別の確率密度関数/確率を使った場合は綺麗に約分されるとは限らないので、その場合は式(13), 式(14)を計算するか、手計算して約分できる項を消した形の式を計算すると良いでしょう。
アルゴリズム的には以下のようにまとめられます。
距離s s s をサンプリング
s < t s < t s < t の場合
[ 0 , 1 ] [0, 1] [ 0 , 1 ] の一様乱数ξ \xi ξ を生成
ξ < P a \xi < P_a ξ < P a ならL e ( x − s ω ⃗ , ω ⃗ ) L_e(x - s\vec{\omega}, \vec{\omega}) L e ( x − s ω , ω ) を評価して終了
ξ ≥ P a \xi \ge P_a ξ ≥ P a なら位相関数からω ⃗ ′ \vec{\omega}' ω ′ を生成し、レイをx − s ω ⃗ x - s\vec{\omega} x − s ω まで進めて新たな方向ω ⃗ ′ \vec{\omega}' ω ′ をセットし、1に戻る
s ≥ t s \ge t s ≥ t の場合はL ( x − t ω ⃗ , ω ⃗ ) L(x - t\vec{\omega}, \vec{\omega}) L ( x − t ω , ω ) を評価する。レイをx − t ω ⃗ x - t\vec{\omega} x − t ω まで進め、別の媒質に入る場合は1に戻る。真空の場合は通常のパストレーシングで計算する
発光がない場合の最適化
媒質が発光しない場合(L e = 0 L_e = 0 L e = 0 )は吸収イベントを選択しても寄与が0となって無駄です。そこで発光がない場合は吸収イベントを選択する確率を0とすることで、モンテカルロ積分の効率を良くすることができます。
この場合、散乱イベントを選択する確率は常に1になります。
P a = 0 P s = 1 \begin{aligned}
P_a &= 0 \\
P_s &= 1
\end{aligned} P a P s = 0 = 1
式(13), 式(14)にこれを代入してあげると以下のようになります。
L ^ ( x , ω ⃗ ) = μ s μ t L i ( x − s ω ⃗ , ω ⃗ ′ ) 1 { s < t } + L ( x − t ω ⃗ , ω ⃗ ) 1 { s ≥ t } (16) \begin{aligned}
\widehat{L}(x, \vec{\omega}) &= \frac{\mu_s}{\mu_t}L_i(x - s\vec{\omega}, \vec{\omega}')\mathbb{1}_{\{s < t\}} \\
&+ L(x - t\vec{\omega}, \vec{\omega})\mathbb{1}_{\{s \ge t\}} \tag{16}
\end{aligned} L ( x , ω ) = μ t μ s L i ( x − s ω , ω ′ ) 1 { s < t } + L ( x − t ω , ω ) 1 { s ≥ t } ( 1 6 )
発光がある場合と比べるとμ s μ t \frac{\mu_s}{\mu_t} μ t μ s の項がL i L_i L i にかかっていることが分かります。この項は 単一散乱アルベド(Single-scattering albedo) と呼ばれます。
最後に
VREのモンテカルロ積分は複雑に見えますが、最終的に出てくるアルゴリズムは意外とシンプルです。個人的には一見数値計算が不可能に見えるVREがこのような確率論的な手法で数値計算出来てしまうことに面白さを感じます。モンテカルロレイトレーシングは確率論の応用として非常に面白い分野だと思います。
こういった計算は原子核物理学の分野でも使われているそうです。そっちの数値計算もいつかやってみたいですね。
今回は一様媒質の場合を扱いましたが、非一様媒質の場合も実はNull collision particleという、衝突しても何もしない粒子で隙間を埋めてあげることで一様媒質に帰着させて計算できます(Delta Tracking )。そのため、非一様媒質に対するモンテカルロレイトレーシングをやる場合でも今回の内容は理論的な基礎になります。
また、今回は吸収係数/散乱係数が波長非依存であると仮定して式の導出を行ってきました。これだと色付きの媒質がレンダリングできないという問題があります。波長依存の場合は波長を最初にランダムに選び、その波長で自由行程サンプリング、吸収/散乱イベントサンプリングを行ったりします。
非一様媒質の場合や吸収係数/散乱係数が波長依存の場合、実装方法などについてもそのうち別の記事で紹介していきたいと思います。
References