穴日記

どうだ明るくなったろう

表面化散乱の実装とかについて

コメント欄で表面化散乱の話があったので簡単に書いておきます。(一か月くらい前ですね。すいません。あまりこっちのブログは見てないのでツイッターとかのほうが反応は良いです)
表面化散乱とは、物体に侵入した光が物体内部で散乱を繰り返し、別の場所から出てくる現象で、人間の肌や大理石のような物体で顕著に影響が現れます。

表面化散乱の実装はだいたい二種類あり、一つはBSSRDFベースのもので、もう一つは直接散乱をシミュレーションするものです。
前者は非常に高速に実現できるのですが、多少実装が面倒な部分も無くもないです。後者は実装は単純ですが、非常に重くなります。

BSSRDFベースのもの

表面化散乱を拡散理論によって近似、さらにDipoleモデルによって近似することでBRDFのように単純な関数の形で散乱現象を取り扱います。
Dipole以外にもMultipoleとか、いろいろモデルはあります。
このモデルをレンダリングに応用するとなると複数の実装が考えられます。
例えば、普通のパストレではレイとサーフェスの交点から次の反射方向を決める際、新しい始点=現在の交点となります。
しかし、内部における散乱をBSSRDFによってモデル化するとなると、新しい始点=現在の交点の「周辺の点」となります。
この周辺の点ですが、具体的にどこになるか、というのがBSSRDFによって何らかの形で記述されます。たいていは現在の交点を中心として、遠くなるほど確率が小さくなるような確率密度関数を考え、その確率密度に基づいて新しい始点とします。さらに、現在の交点と新しい始点の距離に基づいて光を減衰させます。この減衰もBSSRDFによって記述します。一般的には、遠くなるほどたくさん減衰させます。
あとは、新しい始点から再びレイトレースを行っていくだけで、普通のパストレーシングとなんら変わりません。
このようにすると、内部の散乱をシミュレーションしないでも済むため大変高速に表面化散乱を実現できます。一方で、新しい点をどのようにしてサンプリングするか、という問題がありますし、そもそもBSSRDFをどう記述するか、という問題もあります。これらの解決策もいろいろ考えられますが、後はA Practical Model for Subsurface Light Transportという論文を読むのが良いでしょう。

散乱を直接シミュレーションするもの

さて、一方で散乱を直接シミュレーションするというアプローチもあります。
これは、非常に単純で、散乱のためのパラメータ(散乱係数、位相関数など)を決めておいたら、あとは物体内部における散乱を愚直にシミュレーションするだけです。
散乱のシミュレーションについては多少のバリエーションがあります。
例えば、レイマーチングベースの手法なら、現在位置から進行方向に少しずつレイを進めていき、進めるたびに一定確率で散乱・吸収イベントを起こします。(この確率は散乱係数・吸収係数といった対象物体のパラメータになります)吸収が起これば、そこでトレース全体を打ち切ります。散乱が起これば、位相関数の形状に基づいて新しい方向をランダムに決めます。位相関数の形状が球なら、一様にランダムにどこか別の方向になります。
他にも、次の散乱・吸収イベントが起こる位置を直接サンプリングする、という手法があります。散乱係数と吸収係数から、消失係数というものを求めることができます。この消失係数を使うことで、現在位置からどれくらいの距離進んだら次の散乱・吸収イベントが起こるか、について確率密度関数を作れます。この確率密度関数に従って、すすむ距離を直接サンプリングによって得ることもできます。サンプリングした距離進んだら、レイマーチングの場合と同様、散乱・吸収イベントの処理を行います。
BSSRDFの場合と同様、これ以外はパストレーシングと同じで、光源にヒットするまで処理を続けることでレンダリングを行うことができます。