一様媒質のモンテカルロレイトレーシング
2021/12/24
#3dcg #raytracing
モンテカルロレイトレーシングを用いた一様媒質のボリュームレンダリングについて

この記事はレイトレアドベントカレンダー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
BlenderのPrincipled BSDF

こういった表面化散乱以外にも、水や霧のレンダリングに一様媒質を用いることが出来ます。以下はコーネルボックスに霧を充満させてレンダリングした例です。

霧が充満したコーネルボックス
霧が充満したコーネルボックス

光源の周りが霧による光の散乱によってボヤけた感じになっていることが分かります。

このように一様媒質を考慮したレンダリングを行うとレンダリングの表現力が一気に上がります。

以降ではモンテカルロレイトレーシングを用いて一様媒質のレンダリングを行う方法について見ていきます。

ボリュームレンダリング方程式

まずは何を計算すれば良いのかをはっきりさせます。そのために媒質中での放射輝度の変化を記述するRTEとVREという式について見ていきます。

媒質中での放射輝度の変化は以下の 放射輸送方程式(Radiative transfer equation - RTE) によって記述されます。

  • L(x,ω)L(x, \vec{\omega}): 点xxにおいて方向ω\vec{\omega}から来る放射輝度
  • μa(x)\mu_a(x): 点xxにおける吸収係数
  • μs(x)\mu_s(x): 点xxにおける散乱係数
  • Le(x,ω)L_e(x, \vec{\omega}): 点xxにおいて方向ω\vec{\omega}に発光する放射輝度
  • Ls(x,ω)L_s(x, \vec{\omega}): 点xxにおいて方向ω\vec{\omega}へ散乱される外から来た放射輝度
(ω)L(x,ω)=μa(x)L(x,ω)μs(x)L(x,ω)+μa(x)Le(x,ω)+μs(x)Ls(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}
式(1)の概念図
式(1)の概念図

この方程式は方向ω\vec{\omega}に微小距離dsdsだけ移動した時、放射輝度がどのように変化するかを表した式です。各項は次のような物理的意味を持っています。

  • μa(x)L(x,ω)-\mu_a(x)L(x, \vec{\omega}): 吸収による放射輝度の減衰
  • μs(x)L(x,ω)-\mu_s(x)L(x, \vec{\omega}): 散乱(Out-scattering)による放射輝度の減衰
  • μa(x)Le(x,ω)\mu_a(x)L_e(x, \vec{\omega}): 発光(Emission)による放射輝度の増加
  • μs(x)Ls(x,ω)\mu_s(x)L_s(x, \vec{\omega}): 外から入ってきた光の散乱(In-scattering)による放射輝度の増加

吸収係数/散乱係数は本来は波長依存の量ですが、今回は簡単のために波長非依存の量であると仮定して話を進めます。

ここでLs(x,ω)L_s(x, \vec{\omega})は以下のように球面全体での積分で定義されます。

  • S2\mathcal{S^2} 球面全体
  • fp(ω,ω)f_p(\vec{\omega}, \vec{\omega}'): 位相関数
  • Li(x,ω)L_i(x, \vec{\omega}'): 点xxに方向ω\vec{\omega}'から入射する放射輝度
Ls(x,ω)=S2fp(ω,ω)Li(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}
式(2)の概念図
式(2)の概念図

この式は媒質中で周辺から入ってきた光が方向ω\vec{\omega}にどれだけ散乱されるかを表した式です。位相関数fpf_pはボリューム版のBRDFのようなものとして見れます。

式(1)はLsL_sの項が積分を含んでいるので、積分微分方程式 (Integro-differential equation) になっています。このままでは扱いづらいので、両辺を積分して微分を消すことを考えます。

境界条件として点xxから距離ttだけ離れた点xtωx - t\vec{\omega}が媒質の終端にあると仮定すると、距離00からttまで積分することで以下の式を得ます。

  • μt(x)=μa(x)+μs(x)\mu_t(x) = \mu_a(x) + \mu_s(x)
  • T(x,xsω)=e0sμt(xsω)dsT(x, x - s\vec{\omega}) = e^{-\int_0^s \mu_t(x - s'\vec{\omega})ds'}
L(x,ω)=0tT(x,xsω)(μa(xsω)Le(xsω,ω)+μs(xsω)Ls(xsω,ω))ds+T(x,xtω)L(xtω,ω)(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}
式(3)の概念図
式(3)の概念図

この式は ボリュームレンダリング方程式(Volume rendering equation - VRE) と呼ばれます。レンダリング方程式のボリューム版です。

第1項の積分は媒質中から得られる放射輝度の合計を表しています。第2項は媒質の終端から入射する放射輝度を表しています。

T(x,xsω)T(x, x - s\vec{\omega})透過率(Transmittance) と呼ばれます。この関数は光が点xsωx - s\vec{\omega}から点xxまで進んだ時にどれだけ減衰するかを表しています。μt(x)\mu_t(x)消失係数(Extinction coefficient) と言います。

式(3)はLsL_sの項が未知の値Li(x,ω)L_i(x, \vec{\omega}')を含んでいますが、この値は再び式(3)を適用することで計算できます。再帰的な展開を繰り返していくとレンダリング方程式と同様に経路積分形式による表現を得ることができます。今回の内容ではそこまでの定式化は必要ないので、ここでは省略します。

ボリュームレンダリングでは式(3)のボリュームレンダリング方程式を数値計算することが目標になります

ボリュームレンダリング方程式のモンテカルロ積分

モンテカルロレイトレーシングによるボリュームレンダリングでは式(3)をモンテカルロ積分します。以降ではその方法について見ていきます。

第1項の積分では積分変数として距離ssがあるので、これを確率的にサンプリングすることを考えます。

距離ssを表す確率変数をS:Ω[0,)S: \Omega \to [0, \infty)とします(Ω\Omegaは標本空間)。ここではあえてSSの値の範囲を[0,)[0, \infty)にしています。StS \ge tの時は第1項を評価することはできませんが、この時は第2項を評価することにします。つまり距離SSを用いたロシアンルーレットによって第1項と第2項のどちらを評価するかを確率的に選択します。

この時、式(3)のモンテカルロ積分は以下のように書けます。

  • pS(s)p_S(s): 距離SSの確率密度関数
  • 1A\mathbb{1}_A: 指示関数。AAが成立している時に1、そうでない時に0を返す
  • P(St)P(S \ge t): 距離SStt以上の値を取る確率
Term1(s)=T(x,xsω)(μa(xsω)Le(xsω,ω)+μs(xsω)Ls(xsω,ω))Term2=T(x,xtω)L(xtω,ω)L^(x,ω)=Term1(s)pS(s)1{s<t}+Term2P(St)1{st}(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}

これが式(3)の不偏推定量になっていることは以下のように確認できます。

E[L^(x,ω)]=0(Term1(s)pS(s)1{s<t}+Term2P(St)1{st})pS(s)ds=0Term1(s)pS(s)1{s<t}pS(s)ds+Term2P(St)01{st}pS(s)ds=0tTerm1(s)pS(s)pS(s)ds+Term2P(St)P(St)=0tTerm1(s)ds+Term2\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}

距離サンプリングを用いた式(4)の計算の物理的意味について考えてみると、距離ssで媒質中の粒子との衝突が発生し、吸収/散乱が起きたと考えることができます。逆に考えると距離ssまでは粒子との衝突が発生しなかったということです。そのためこのような距離ssのサンプリングは 自由行程サンプリング(Free-path sampling) と呼ばれます。

自由行程サンプリング
自由行程サンプリング

続いてSSにどのような確率分布を設定するべきかについて考えていきます。

SSの確率分布の設定

式(4)を見ると、透過率TTが各項にかかっていることが分かります。SSの確率分布を透過率TTに比例させれば重点的サンプリングが行えるので、そのようにします。

SSの確率密度関数をpS(s)p_S(s)とします。比例定数kkを用いて以下のようにSSの確率密度関数を透過率に比例させます。

pS(s)=kT(x,xsω)p_S(s) = kT(x, x - s\vec{\omega})

これが確率密度関数になるためには0pS(s)ds=1\int_0^{\infty} p_S(s)ds = 1を満たす必要があります。なので、そうなるようにkkを取ることを考えます。

今考えているのは一様媒質なので、μt(x)\mu_t(x)の値は媒質中で一定です。この場合は透過率TTを以下のように解析的に書くことができます

T(x,xsω)=e0sμt(xsω)ds=e0sμtds=eμts(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}
一様媒質の場合の透過率
一様媒質の場合の透過率

式(5)を使って0pS(s)ds\int_0^{\infty} p_S(s)dsを計算すると以下のようになります。

0pS(s)ds=k0T(x,xsω)ds=k1μ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}

これが1になれば良いので、k=μtk = \mu_tとすれば良いです。まとめると距離SSの確率密度関数は以下のようになります。

pS(s)=μtT(x,xsω)=μteμts(6)\begin{aligned} p_S(s) &= \mu_t T(x, x - s\vec{\omega}) \\ &= \mu_t e^{-\mu_t s} \tag{6} \end{aligned}

これは指数分布の確率密度関数と同じです。つまりSSは平均1μt\frac{1}{\mu_t}の指数分布に従っています。

これでSSの確率分布を設定できたので、次はサンプリング方法について見ていきます。

SSのサンプリング

今回の場合SSの累積分布関数は解析的に求めることが出来るので、逆関数法を用いてSSのサンプリングを行います。

SSの累積分布関数FS(s)F_S(s)を計算すると以下のようになります。

FS(s)=0spS(s)ds=1eμts(7)\begin{aligned} F_S(s) &= \int_0^s p_S(s)ds \\ &= 1 - e^{-\mu_t s} \tag{7} \end{aligned}

累積分布関数の逆関数を求めると以下のようになります。

FS1(u)=log(1u)μtF_S^{-1}(u) = -\frac{\log(1 - u)}{\mu_t}

[0,1][0, 1]の一様乱数をξ\xiとして、FS1(ξ)F_S^{-1}(\xi)を計算すれば距離SSのサンプルssを得ることができます。

s=log(1ξ)μt(8)s = -\frac{\log(1 - \xi)}{\mu_t} \tag{8}

これで重点的サンプリングを用いて距離SSのサンプルを発生させることが出来るようになりました。実際に式(8)を計算してssのサンプルを発生させてみると以下のようになります。

sのヒストグラム
sのヒストグラム

大体指数分布に従っている様子が分かります。

次は式(4)の各項の評価方法について見ていきます。

Term1\mathrm{Term1}の評価

Term1\mathrm{Term1}は以下のような定義でした。

Term1(s)=T(x,xsω)(μa(xsω)Le(xsω,ω)+μs(xsω)Ls(xsω,ω))\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)

今考えているのは一様媒質なので、μa\mu_a, μs\mu_sは定数になります。そのため以下のように書き直しておきます。

Term1(s)=T(x,xsω)(μaLe(xsω,ω)+μsLs(xsω,ω))\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)

今、距離SSのサンプリングを行ってssが得られているとします。TTは解析的に書くことができているので、簡単に計算できます。

T(x,xsω)=eμttT(x, x - s\vec{\omega}) = e^{-\mu_t t}

問題はLeL_eLsL_sの項です。これらの項は両方評価しても良いですが、LsL_sの評価は再びVREを適用することになるので重いです。そこでロシアンルーレットを行ってLeL_eLsL_sのどちらを評価するかを確率的に決めることにします。これをここでは 吸収/散乱イベントサンプリング と呼ぶことにします。吸収イベントが選択されたらLeL_e, 散乱イベントが選択されたらLsL_sを評価するようにします。

吸収/散乱イベントのサンプリング

吸収イベントを選択する確率をPaP_a, 散乱イベントを選択する確率をPs=1PaP_s = 1 - P_aとします。[0,1][0, 1]の一様乱数をξ\xiとして、ロシアンルーレットによるTerm1\mathrm{Term1}の評価は以下のように書けます。

Term1^(s)=T(x,xsω)(μaLe(xsω,ω)Pa1{ξ<Pa}+μsLs(xsω,ω)Ps1{ξPa})(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}

ここで問題なのはPaP_a, PsP_sをどのように設定するかです。式を見ると各項にはμa\mu_a, μs\mu_sがかかっているため、これを使って重点的サンプリングをすることを考えます。以下のようにPaP_a, PsP_sを設定すれば良いです。

Pa=μaμtPs=μsμt(10)\begin{aligned} P_a &= \frac{\mu_a}{\mu_t} \\ P_s &= \frac{\mu_s}{\mu_t} \tag{10} \end{aligned}

μt=μa+μs\mu_t = \mu_a + \mu_sだったので、PaP_a, PsP_s[0,1][0, 1]の範囲の値を取って確かに確率になっています。

他にもPaP_aμaLe\mu_a L_eの値に比例させるといった設定の仕方があるでしょう。ここでは簡単のために以上の設定のままで考えます。

吸収イベントが選択された場合はTμaLePaT\frac{\mu_a L_e}{P_a}を評価するだけです。散乱イベントが選択された場合はTμsLsPsT\frac{\mu_s L_s}{P_s}を評価します。

LeL_eは簡単に評価できますが、LsL_sは積分を計算しなければいけないので厄介です。次はLsL_sの計算方法について見ていきます。

LsL_sの評価

LsL_sは以下のような定義でした。

Ls(x,ω)=S2fp(ω,ω)Li(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}')

これもモンテカルロ積分で評価することを考えます。 ランダムな方向を表す確率変数をD:ΩS2D: \Omega \to \mathcal{S}^2とし、DDの確率密度関数をpD(ω)p_{D}(\vec{\omega})とします。DDから方向ωi\vec{\omega}_i'をランダムにNLsN_{L_s}個生成したとすると、LsL_sのモンテカルロ積分は以下のように書けます。

Ls^(x,ω)=1NLsi=1NLsfp(ω,ωi)Li(x,ωi)pD(ω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}

重点的サンプリングを考えると、DDの確率分布はfpf_pに比例するように取った方が良いです。ここで位相関数には以下のように全球で積分すると1になる性質があります。

S2fp(ω,ω)dσ(ω)=1\int_{\mathcal{S}^2} f_p(\vec{\omega}, \vec{\omega}')d\sigma(\vec{\omega}') = 1

つまり、fpf_pは比例定数で正規化しなくても、そのまま確率密度関数として使えます。なのでpD(ω)p_D(\vec{\omega}')には位相関数をそのままセットします。

pD(ω)=fp(ω,ω)p_D(\vec{\omega}') = f_p(\vec{\omega}, \vec{\omega}')

レンダリングでは位相関数として以下の Henyey-Greenstein phase function がよく使われます。以下HG位相関数と呼ぶことにします。

  • θ\theta: ω\vec{\omega}ω\vec{\omega}'のなす角
  • gg: 散乱方向を制御するパラメーター
fp(ω,ω)=14π1g2(1+g2+2gcosθ)32f_p(\vec{\omega}, \vec{\omega}') = \frac{1}{4\pi}\frac{1 - g^2}{(1 + g^2 + 2g\cos\theta)^\frac{3}{2}}
g = 0.5の場合のHG位相関数
g = 0.5の場合のHG位相関数

HG位相関数では逆関数法を用いて位相関数からの方向サンプリングが行えます。ここではそれについては解説しませんが、気になる方は以下のPBRTのページが参考になります。

位相関数を用いて方向ωi\vec{\omega}_i'を生成できた後はLi(x,ωi)L_i(x, \vec{\omega}_i')を評価します。この項は媒質中で点xxに方向ωi\vec{\omega}_i'から入射する放射輝度を表しているので、計算にはVREが再び使えます。つまりLiL_iを式(4)を用いて再帰的に評価します。

VREの再帰的な適用
VREの再帰的な適用

式(11)は方向サンプルを複数個取る一般的な場合も含めて記述していますが、実際にはNLs=1N_{L_s} = 1とします。LsL_sの評価は再帰的に行うので、NLs>1N_{L_s} > 1だと再帰の回数が爆発するためです。以降では以下のようにNLs=1N_{L_s} = 1として話を進めます。

Ls^(x,ω)=fp(ω,ωi)Li(x,ω)pD(ω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}

次は残りのTerm2\mathrm{Term2}の評価についてです。

Term2\mathrm{Term2}の評価

Term2\mathrm{Term2}は以下のような定義でした。

Term2=T(x,xtω)L(xtω,ω)\mathrm{Term2} = T(x, x - t\vec{\omega})L(x - t\vec{\omega}, \vec{\omega})

TTは解析的に書くことができているので簡単に評価できます。

T(x,xtω)=eμttT(x, x - t\vec{\omega}) = e^{-\mu_t t}

L(xtω,ω)L(x - t\vec{\omega}, \vec{\omega})は媒質の終端から来る放射輝度を表しているのでした。媒質の終端の隣が別の媒質の場合にはVREを再び適用することができます。つまり、L(xtω,ω)L(x - t\vec{\omega}, \vec{\omega})を式(4)で再帰的に計算していきます。

媒質の終端が別の媒質の場合
媒質の終端が別の媒質の場合

媒質の終端の隣が真空の場合はレンダリング方程式を使ってL(xtω,ω)L(x - t\vec{\omega}, \vec{\omega})を計算することができます。この場合は通常のパストレーシングを使ってL(xtω,ω)L(x - t\vec{\omega}, \vec{\omega})を計算すれば良いです。

媒質の終端が真空の場合
媒質の終端が真空の場合

アルゴリズムの全体像

これまで説明してきたことをまとめると、一様媒質の場合のVREのモンテカルロ積分は以下のように書けます。

  • ss: 距離サンプル
  • ξ\xi: [0,1][0, 1]の一様乱数
L^(x,ω)=T(x,xsω)(μaLe(xsω,ω)Pa1{ξ<Pa}+μsLs^(xsω,ω)Ps1{ξPa})pS(s)1{s<t}+T(x,xtω)L(xtω,ω)P(St)1{st}(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}
Ls^(xsω,ω)=fp(ω,ω)Li(xsω,ω)pD(ω)(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}

TTpSp_Sなどは以下のような定義でした。

  • 透過率: T(x,xsω)=eμtsT(x, x - s\vec{\omega}) = e^{-\mu_t s}
  • 距離SSの確率密度関数: pS(s)=μtT(x,xsω)p_S(s) = \mu_t T(x, x - s\vec{\omega})
  • Term2\mathrm{Term2}を評価する確率: P(St)=1FS(S<t)=T(x,xtω)P(S \ge t) = 1 - F_S(S < t) = T(x, x - t\vec{\omega})
  • 吸収イベントを選択する確率: Pa=μaμtP_a = \frac{\mu_a}{\mu_t}
  • 散乱イベントを選択する確率: Ps=μsμtP_s = \frac{\mu_s}{\mu_t}
  • 散乱方向DDの確率密度関数: PD(ω)=fp(ω,ω)P_D(\vec{\omega}') = f_p(\vec{\omega}, \vec{\omega}')

これらを式(13), 式(14)に代入してあげると以下のようになります。

L^(x,ω)=(Le(xsω,ω)1{ξ<Pa}+Li(xsω,ω)1{ξPa})1{s<t}+L(xtω,ω)1{st}(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}

TTpSp_Sなどが消えて、非常にシンプルな形になってくれました。実際に実装する上では式(13), 式(14)を計算するのではなくて、代入して約分した形の式(15)を計算するほうが計算量が少なくて良いでしょう。ただしこの綺麗な形の式が出てくるのはpSp_S, Pa,PsP_a, P_s, pDp_Dなどをそうなるように取ったためです。別の確率密度関数/確率を使った場合は綺麗に約分されるとは限らないので、その場合は式(13), 式(14)を計算するか、手計算して約分できる項を消した形の式を計算すると良いでしょう。

アルゴリズム的には以下のようにまとめられます。

  1. 距離ssをサンプリング
  2. s<ts < tの場合

    1. [0,1][0, 1]の一様乱数ξ\xiを生成
    2. ξ<Pa\xi < P_aならLe(xsω,ω)L_e(x - s\vec{\omega}, \vec{\omega})を評価して終了
    3. ξPa\xi \ge P_aなら位相関数からω\vec{\omega}'を生成し、レイをxsωx - s\vec{\omega}まで進めて新たな方向ω\vec{\omega}'をセットし、1に戻る
  3. sts \ge tの場合はL(xtω,ω)L(x - t\vec{\omega}, \vec{\omega})を評価する。レイをxtωx - t\vec{\omega}まで進め、別の媒質に入る場合は1に戻る。真空の場合は通常のパストレーシングで計算する

発光がない場合の最適化

媒質が発光しない場合(Le=0L_e = 0)は吸収イベントを選択しても寄与が0となって無駄です。そこで発光がない場合は吸収イベントを選択する確率を0とすることで、モンテカルロ積分の効率を良くすることができます。

この場合、散乱イベントを選択する確率は常に1になります。

Pa=0Ps=1\begin{aligned} P_a &= 0 \\ P_s &= 1 \end{aligned}

式(13), 式(14)にこれを代入してあげると以下のようになります。

L^(x,ω)=μsμtLi(xsω,ω)1{s<t}+L(xtω,ω)1{st}(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}

発光がある場合と比べるとμsμt\frac{\mu_s}{\mu_t}の項がLiL_iにかかっていることが分かります。この項は 単一散乱アルベド(Single-scattering albedo) と呼ばれます。

最後に

VREのモンテカルロ積分は複雑に見えますが、最終的に出てくるアルゴリズムは意外とシンプルです。個人的には一見数値計算が不可能に見えるVREがこのような確率論的な手法で数値計算出来てしまうことに面白さを感じます。モンテカルロレイトレーシングは確率論の応用として非常に面白い分野だと思います。

こういった計算は原子核物理学の分野でも使われているそうです。そっちの数値計算もいつかやってみたいですね。

今回は一様媒質の場合を扱いましたが、非一様媒質の場合も実はNull collision particleという、衝突しても何もしない粒子で隙間を埋めてあげることで一様媒質に帰着させて計算できます(Delta Tracking)。そのため、非一様媒質に対するモンテカルロレイトレーシングをやる場合でも今回の内容は理論的な基礎になります。

また、今回は吸収係数/散乱係数が波長非依存であると仮定して式の導出を行ってきました。これだと色付きの媒質がレンダリングできないという問題があります。波長依存の場合は波長を最初にランダムに選び、その波長で自由行程サンプリング、吸収/散乱イベントサンプリングを行ったりします。

非一様媒質の場合や吸収係数/散乱係数が波長依存の場合、実装方法などについてもそのうち別の記事で紹介していきたいと思います。

References