そもそも顔のいろはどうするのか

ここまでで皮膚の表面の鏡面反射についてと、皮下散乱について考えてきたが、実は根本的なことを1つ忘れている。

それは、(顔の)テクスチャをどうするかという問題。

この部分をどうするか議論していなかった

例えば顔ならば頬、唇、シワ、肌のきめの凹凸……といった顔テクスチャを用意して適用する。この皮膚テクスチャはどうやって適用するのがよいのか、ということも考えなければならない。

最も単純なのが普通にピクセル単位に法線ベクトルNと、光源ベクトルLに配慮した拡散反射のライティングをしてこれにテクスチャ色を掛けるというもの。これは拡散反射の陰影処理をしてテクスチャを適用する際の最も基本的なスタイルだ。

一見、問題なしのように見えるが、この結果から皮下散乱のボカしを行ってしまうと、肌のテクスチャ模様のディテールまでもがぼけてしまい、ちょっともったいない。

普通に拡散反射の陰影処理をしてテクスチャマッピングすると

こんな感じになる。一見問題なさそうに見えるがディテールが失われてしまっている

そこで第二案として提唱されるのが、最初には顔画像テクスチャには全く触らず、各ピクセル単位に拡散反射だけを計算してこの答えだけをテクスチャへと出力し、これに対して皮下散乱のボカし処理を行い、そのボカし処理結果とテクスチャを掛け合わせるというアイディア。

NVIDIAによれば「これは写真などから作成したテクスチャとは相性がよい」ということであった。

これは写真ベースの皮膚テクスチャは写真を撮影した時点で皮膚の肌理やしわの微細凹凸が、撮影時点で皮下散乱をしていて適度にぼやけていて、疑似皮下散乱の結果との相性がいいためらしい。

ブラーさせる元ネタは拡散反射の方程式の解だけで作り、これをブラーさせてから顔テクスチャと掛け合わせて適用する方法はどうか

悪くはないが今度はディテールが強く残りすぎという感じがする

しかし、写真ではなく、アーティストが、シワや肌の肌理の表現のためにゼロから起こした、はっきりとした微細凹凸やシワのテクスチャだと、この2番目の方法ではディテールが逆に残りすぎて不自然になる。

なんとか適度にディテールを残しつつぼかすようなことができないだろうか。

と、そこで、前出のWeyrichらはユニークな2つの中間的な方法を考案する。

それは最初の、皮下散乱のボカし処理に用いるためのテクスチャ素材作成パスでのテクスチャ色の掛けあわせには、テクスチャ色を減退させ、ボカし処理結果に対してももう一回減退させたテクスチャ色を掛け合わせるというもの。

ボカし処理の前後でテクスチャ適用をする。ただ値を半分(1/2)にしただけのものを適用していては意味がない。半々にしたいならば掛け合って元に戻る平方根を取るべき

ボカし前後にテクスチャ値の平方根同士を掛けるようにしたらまずまずの感じに

演算の観点から見るとテクスチャ色が2回掛け合わされることになるのでこの"減退"の具合はキーポイントになってくる。例えば前段階(ボカし前)で半分、後ろ段階(ボカし後)で半分としてただ1/2としてのでは1/2×1/2で1/4となってしまう。2乗で元に戻ればいいのだから、例えば半分であれば平方根を用いればいい。

ただ「半分で決め打ち」という定数処理では調整が面倒なので、これを一般化するために「べき乗演算」(pow関数)を用いる。例えばXの平方根はXの1/2乗だ。NVIDIAの実験では前段階ではテクスチャ色を0.82乗し、後ろ段階では0.18乗した減退率パラメータを用いたとのこと。

これは一見、荒唐無稽に思えるが実は物理的にも意味があるとしている。

光はディテール層(光吸収層)に入射もするが、内部で散乱して再び戻ってきてここから出射もするので、実際問題として2回ここに関わってくる。この前後のテクスチャ色の掛け合わせは丁度この処理を近似的に行ったことに相当する、というのだ。

顔テクスチャは光の吸収層だと仮定すれば、光が入射するときと出射するときの2回影響を受ける

だからこのボカし処理の前後で吸収層(≒顔テクスチャ)について処理するのは物理的な意味合いとして正しい

平方根ではボカし処理前後でテクスチャの影響が半分ずつ……という固定形になってしまうので、任意の"根"を採用して一般化して調整可能にする。NVIDIAでは前段階で0.82を採用

疑似シェーダコード。ただし、この例では平方根(前後0.5ずつ)の固定バランスになっている