皮下の光散乱をどう実装するか?

続いて着目するのが94%の残りの光について。

これらについて表現するには何らかの方法で皮下散乱を再現する必要がある。

ただ、これは光が皮膚下でどういう経路で伝搬したかを考えなければならず、その経路の種類は膨大だ。今、描画しようとしている肌のピクセルは他の位置から入射した光の影響があるかもしれないし、逆にここに入射している光が吸収されるのかもしれない。これではとてもリアルタイムで計算できない。

残りの94%の光の経路、皮下散乱について考える

そこで、まともに計算できないのであれば、これを諦めて問題をより簡単にすることを考える。

そこで「光が散乱して再び出てくるまでの平均距離はどのくらいなのか」「光が吸収されてしまう平均頻度はどのくらいなのか」ということにだけ配慮する。

また、入射光のおよそ1/10が最初の脂質層を突破するものの、この時点で光の指向性は失われ拡散光となる。つまり、1/10の光についての皮下散乱を考えればよく、しかもそ散乱光の出力光は指向性のない拡散光なので話は意外に簡単なものに思えてくる(その他の光は吸収されるか、あるいは前述したフレネル項付きの鏡面反射をする)。

入射光のおよそ1/10が最初の脂質層を突破するものの、この時点で光の指向性は失われ拡散光となる

それでは、結局のところ、入射光に対して拡散反射の陰影処理を行って画像の皮膚テクスチャと乗算して、前述のフレネル項付きの鏡面反射を追加するだけではよいのではないか。

しかし、これはあまり芳しくなく、まるでDirectX 8世代の人肌表現で、かなり乾いた感じに見えてしまう。

これはよく考えると当たり前のこと。

あるピクセルから出てくる拡散反射光はそのピクセルに入射した光が拡散しただけではない。隣接する他のピクセルに入射した光が皮膚内で散乱して出てきた拡散光も含まれるからだ。実はこれが皮膚のしっとりとした透明感表現と深い関係がある。

「拡散反射×テクスチャ+フレネル項付きの鏡面反射」ではこんな感じに乾いて見えてしまう

これがうまくいかないのは皮膚下で散乱した光も出てくるときに拡散反射していることを無視していたため

そこで、どうすればリアルな皮下散乱を再現できるのか、NVIDIAでは様々な文献を調査したという。

真皮層の光の経路のランダム性に配慮したモンテカルロレンダリングなどもあったが、これらは到底リアルタイムで実装できるものではない。

そんななか彼らがピックアップしたのが、Craig DonnerとHenrik WannらがSIGGRAPH 2005で発表した「Light Diffusion in Multi-Layered Translucent Materials」という論文だ。

彼らの論文では、三層の皮膚モデルを採用し、医療業界、光学系業界で測定された散乱パラメータを用い、3Dモデルのデジタイズサービス企業であるXYZRGB社の高精度頭部モデルを用い、数分のレンダリング時間でリアルな顔をレンダリングする技術を発表していた。NVIDIAが、彼らの論文で着目した点は、皮膚の光散乱は単層ではなく複数層として処理した方がリアルに見えるという部分であった。

三層の皮膚モデルで皮下散乱をシミュレーション

乾いた感じが消えてリアルに見える

下層に行けば行くほど散乱が広くその色は赤にシフトする

単層の皮膚では散乱範囲が狭く、見た目として蝋人形っぽくなってしまう。そしてまた、下層に行くほど散乱範囲が広く、そして赤色が強く出る傾向にある。

ではどうやってこの多層の皮膚の皮下散乱を再現するか。

結局、陰影処理を行うのは顔モデルの表面(のポリゴン上のピクセル)だけなので、ならば、まずは光をある点に入射したときに、その周辺に対してどのような拡散光が帰ってくるのかを調べてみる。

これは、一本の光のビームを皮膚に対して垂直に照射したときに照射点から半径rではどんな色の光がどのくらいの明るさになっているかを求めて計測する。この結果を特に「反射率拡散プロファイル」(RDP:Reflectance Diffusion Profile)と呼ぶ。

ここで、このRDPにおいて、光の赤R,青B,緑Gで半径距離と反射率との関係が全く異なっているという点について注目しておきたい(後述)。

皮膚に照射した一方の光ビームが皮膚下でどのように散乱して出てくるのかをその分布を測定

縦軸が反射率(出射光の輝度)と横軸が光を照射した位置からの距離。つまり遠くに行けば行くほど赤が強く残ることを意味している