鍛冶屋のしわマップ

計画を立てるとき ブラックスミスを企画したとき、カスタムスキンシェーダーの優先順位を高く設定したことはなかった。しかし、それでも私たちは、チャレンジャーの表情をもう少し生き生きとさせるために、何か簡単なことができないかと考えていた。簡単なブレインストーミングの後、ブレンドシェイプを使ったリンクル・マップをプロジェクトに加えることにした。
表情にディテールと深みを加えるために、スタンダードシェーダーは、シワが法線とオクルージョンの両方に影響を与えるようにすれば、最高の効果が得られると判断しました。また、特定の表情が顔の特定の部分に与える影響を制限する方法も欲しかった。
リンクル・マップ・ドライバー
私たちは、アニメーターがメッシュのブレンドシェイプごとに1レイヤーずつ、しわのレイヤーを定義できるコンポーネントを作りました。レイヤー定義には、テクスチャマッピングと強度修飾子、および顔パーツのマスキングテクスチャにマッチするマスキングウェイトのセットが含まれていた。マスキングウェイトを使えば、特定のシワのレイヤーが、マスクされた顔のパーツの1つから4つに、それぞれ異なる影響を与えることができる。

常に4つの異なる表現をブレンドできるようにしたかったので、ブレンドだけでも、すべてのベルとホイッスルを有効にした11のテクスチャサンプラーが必要でした(2つのベーステクスチャ、8つのディテールテクスチャ、1つのマスキングテクスチャ)。このための唯一の現実的な選択肢は、オフスクリーンのプリレンダーパスでブレンドされたリンクルマップを合成することだった。ARGB2101010レンダーテクスチャフォーマットは、10ビットチャンネルのうちの2つに法線を詰め込むことができ、残りの1つにオクルージョンを受け取ることができるため、私たちにとって完璧であることがわかりました。各フレームで、リンクルマップコンポーネントは最も影響力のある4つのブレンドシェイプを見つけ、それに応じてレイヤーのレンダリングウェイトを割り当てる。

すべてのしわのデータをスクリーン空間に合成したら、あとは顔のレンダリングに使っているスタンダードシェーダーの法線とオクルージョンのデータ入力をリダイレクトするだけだ。実際には、これはサーフェス・シェーダーのメイン関数にほんの数行を追加するだけだった。
// Sample occlusion and normals from screen-space buffer when wrinkle maps are active
#ifdef WRINKLE_MAPS
float3 normalOcclusion =
tex2D(_NormalAndOcclusion, IN.screenPos.xy / IN.screenPos.w).rgb;
o.Occlusion = normalOcclusion.r;
#ifdef _NORMALMAP
o.Normal.xy = normalOcclusion.gb * 2.f - 1.f;
o.Normal.z = sqrt(saturate(1.f - dot(o.Normal.xy, o.Normal.xy)));
#endif
#endif最終結果
ベースとなるヘッドと、フルウェイトで大げさに怒ったブレンドシェイプを比較すると、ブレンドされたしわマップによってディテールが追加されていることがわかる:


また、完全にブレンドされたオクルージョンと法線マップを簡単に視覚化できるように、さまざまなデバッグ出力モードを追加した。これらは、最終的な結果において、どのコンポーネントが何に貢献したかを正確に把握するのに非常に役立った。

この機能は、アセットストアから入手できるサンプルプロジェクトにまとめました。基本的には、『鍛冶屋』で使ったいくつかの表現にチャレンジャーの頭をつけただけだが、自分のプロジェクトでこのシステムを動かすための出発点として役立つはずだ。
