カテゴリー別アーカイブ: 未分類

俺式肌シェーダーの作り方(NINGYOU Shaderのしくみ)

この記事を読む前の注意点

この記事は長年勉強してきた上で、3DCGのシェーダについての不満点をぶちまけているため、個人的な見解も含まれている点に注意してください。

非リアル系シェーダーがほしい

Unityでは、マルチプラットフォームで動かすための仕組みがベースとなっているため、シェーダー部分についてはあまり複雑にしていないという経緯があり、ずっとPC向けに改造が行われてきたUnreal系エンジンとは経緯が異なっており、ベースとなるグラフィックのパイプラインが大きく異なっています。
最近はPBRやIBLのしくみが標準に入ったため、やる気があればUE4と似たような(厳密に同じパイプラインにするのは無理ですが)質感を出せるようになりました。

ただ、トゥーン系シェーダーに関しては、あまりてこ入れが少ないように思えます。海外ではトゥーンシェーダーの需要が極端に少なく、シェーダーでやるより、テクスチャに直接陰影を書き込んだテクスチャのほうがモデラーもグラフィックプログラマー使いやすいということもあり、トゥーンシェーダーのノウハウが蓄積されていません。(最近のDisneyが出しているペーパーを見ても、トイストーリー以降の映画の傾向から見て取れるように、セルタッチのアニメを作ることはあまり考えてなさそうです。近年では「プリンセスと魔法のキス」ぐらいでしょうか)
なので、自分で作ってしまえ、ということで作られたのがNINGYOU Shaderになります。

次は問題提起になります。

Diffuse反射の問題点

現在3DCGにおけるDiffuse反射と呼ばれるものは、
光源から対象面に光があたり、視線に入ってくる光は、必ずDiffuseに設定されたテクスチャ色の線形値になるという前提で作られています。

ランバート反射だろうがオーレン・ネイヤー反射だろうが放射輝度でしかとらえておらず、標準のDiffuse反射は多層構造を想定してても、表層と下位の層で反射する波長が同じであると定義しており、人の肌のように表層と下位の層で反射する波長が違うマテリアルには対応できません。

たいていの場合、Subscattering Surface(以下SSS)で吸収させるようにしていますが、レンダリングコストが高いものが多いです。

SSSとの差異について

SSSはボリュームメトリックなものに対して使われており、まともに計算する(BSSRDFからモデルを組み立てる)と重いので、基本はBSSRDFからBRDFへモデルを落とし込む関数が使われています。ゲームの場合は大抵人の肌用に専用のシェーダを使っていることが多いです。

どうやって解決した?

一番簡単なのは、光源方向と面法線の内積値(Lambert反射)に対して色感に変化をもたせるよう、Diffuseスペクトルを用意するとBSSRDFからBRDFへの落とし込み関数を擬似的に定義することができます。MMDのセルシェーダー用として、Diffuseスペクトルの画像ファイルが用意されているモデルも結構あります。
これはマテリアル単位ですが、テクスチャのピクセルごとに用意すればぐっと良くなります。

NINGYOU Shaderではカラーテクスチャに対して、自動的にDiffuseスペクトルを用意するように設計しています。

NINGYOU Shaderを使って、Diffuseスペクトルを比較する

普通のシェーダとNINGYOU Shaderで、Diffuse(光源方向と面法線の内積値)による色感の変化の比較をしてみました。
テクスチャは陰影書き込みをしていないもので、以下の単一色を使っています。

普通のシェーダです。Diffuseスペクトルの色味に変化がないケースです。

NINGYOU Shaderで内積値に変化してDiffuseスペクトルの色味に変化をもたせたものです。

このように、Diffuseスペクトルに手を加えるだけで、肌のような質感を持つマテリアルがうまく表現できるようになります。

今後の展望など

NINGYOU Shaderではまだセルシェーダーは実装していないので、今後入れていきたいと思っています。