ハーフライフ2の方法はあくまで簡易的でそれらしく見せるための工夫であった。

実際の人間の皮膚の陰影は、表皮に当たった光が単純に反射したり拡散したりするだけで決まらない。入射した光は表皮で反射、拡散するだけでなく、皮膚の下に浸透して皮膚下で乱反射して再び表皮から飛び出してくるものもある。皮膚の陰影は非常に複雑な光の経路の集大成によるものなのだ。

この光が皮膚下で散乱する現象を「皮下散乱」(Subskin Scattering)といい、こうした半透明物体に光が浸透して内部で散乱してから飛び出してくるような一般現象を「表面下散乱」(Subsurface Scattering)という。

また、人間の皮膚の陰影処理向けに特別設計したシェーダを「スキン・シェーダ」と呼び、このスキンシェーダの実装には表面下散乱の何らかの実装が避けられないとしている。

なお、前回までで紹介したハーフ・ランバート・ライティングと鏡面反射分布の調整による疑似的な皮膚表現は、皮下散乱こそ無視しているが、皮膚表現向けにチューニングしたということで広義にはスキンシェーダといっても間違いではないかもしれない。

表皮における反射、皮下における散乱

表面下散乱をまじめに実装しての人肌の陰影処理はとても複雑そうに思える。

しかし、要素の一つ一つを分けて考え、それぞれの要素を近似モデルや簡易的に再現していくことでなんとか実現できるかもしれない。NVIDIAはこう考え、同社のGeForce 8800シリーズ用のデモ「Adrianne」向けのスキンシェーダの開発に乗り出したのだという。

さて、皮膚は大まかに考えると、下図のように薄い脂質部分、表皮、真皮という層に分かれる。

人間の皮膚の断面図

測定によれば入射した光の6%までが脂質層までで反射してしまい、残りの94%が皮下の影響を受けるのだという。

大ざっぱに考えれば皮膚の最表層における反射と、皮膚下散乱の2つの処理に分けて考えれば実装できるのではないか、と思えてくる。

皮下散乱の概念図

脂質層における反射

まずは脂質層までに起こる反射について考えてみる。

脂質層での反射の陰影処理は、リアルタイム3Dグラフィックスでは、フォン(Phong)シェーディングやブリン(Bling)シェーディングといった反射方程式を用いるのが一般的だ。

しかし、NVIDIAによれば、皮膚面を掠めるような角度で見た場合のハイライトの出方が、ブリンシェーディングやフォンシェーディングでは、人肌の実物とは違いすぎるため、「人肌の表現には適さない」としている。

そこで、NVIDIAが選択したのはCsaba Kelemen、Laszlo Szirmay-Kalosらが2001年に発表した「A Microfacet Based Coupled Specular-Matte BRDF Model with Importance Sampling」の論文ベースのKS BRDF法だ。KSはKelemenとSzirmay-Kalosの頭文字、BRDFはBidirectional Reflectance Distribution Functionの略で、日本語訳では双方向反射率分布関数となる。

BRDFとは簡単にいうと、光がどう反射するかを光学現象に沿った考え方で一般化したものだ。BRDFの実装法としては「どう反射するか」を1つの方程式で表すことが困難な場合は、測定器を使って測定しデータテーブル(テクスチャデータ)を作成し、これをレンダリング時に参照して陰影計算に用いる方法がよくみられる。NVIDIAが実装した鏡面反射のBRDFは超微細な凹凸を表面にもつ材質の表現に適したベックマン分布(Beckmann Distribution)で、計算負荷低減のためにベックマン分布を事前計算してテクスチャデータに落とし込んでいる。

光と3Dモデルの位置関係は同じにして、見る位置を変えた場合のフォンシェーディングとKS BRDF法との比較図。正面から見た場合(上段)はあまり違いが見られないが、ハイライトの出る面を掠める角度で見た場合(下段)では明らかにハイライトの出方が違う。KS BRDF法の方がリアルだ

結局、NVIDIAの実装では、皮膚の表面の陰影計算には法線ベクトル(N)、視線ベクトル(V)、光源ベクトル(L)という三大要素の他に、鏡面反射強度(ρs)、面の粗さ(m)、屈折率(η)に配慮することになる。

ρsとmは前節でも登場したが、鏡面反射強度はハイライトの強さに相当し、面の粗さは超微細面の傾きを表す。感覚的には面の粗さは値が小さいほどハイライトが狭く鋭くなる傾向がある。屈折率ηは後述するフレネル反射の計算に用いる。

ρsとmは前節で紹介した「Analysis of Human Faces using a Measurement-Based Skin Reflectance Model」(Tim Weyrich,SIGGRAPH 2006)の顔の10個のエリアについての測定情報を参考にすればよいわけだが、NVIDIAの実装では、かなり大ざっぱにこの測定結果から適当に見繕った平均値ρs=0.18、m=0.3という定数を利用したとしている。

左が鏡面反射強度ρsの分布テクスチャ、右が面の粗さmの分布テクスチャ

左が適当に設定した平均値を用いた定数ρs,mによる結果。右は測定値ベースでρs,mの分布テクスチャを元にした結果。NVIDIAのBRDFベースの実装ではあまり大きな差はないと判断した

フレネル反射は、この連載では水面編にて解説しているが、もう一度簡単に概念をおさらいすると、水面の見え方で言えば、「水面上の映り込みと水底の見え具合いを調整するもの」という処理に相当する。一般的には入射した光が視線に対してどういう角度の時にどれだけ反射するか/屈折するかを表すものになる。

人の顔でも光と視線の角度関係によってハイライトの出方が異なるのでこれに配慮しようというわけだ。この計算には屈折率ηが大きく関わってくるうえに、実際の人間の顔では人によって部位によっても異なるとされる。NVIDIAの実装では全体の平均とされるη=1.4(法線入射での反射率としては0.028)を使用したとしている。細かいことを言えばフレネル反射の方程式は定義通りではなく、よく用いられるフレネル反射の高速近似形であるSchlickの近似式を用いている。

左が定義通りのフレネル反射計算を行った結果。右がSchlickのフレネル近似計算による結果

なお、算出したハイライトの色は、顔の画像テクスチャの色に配慮する必要はなく光源色そのままでよいとしている。つまり、光源が白色光ならばハイライトは明るい肌色ではなく、その白色でいいということになる。(続く)

(トライゼット西川善司)