なぜ顔だけ別の陰影制御が必要になるのか

一般的なセルシェーディングでは、表面法線Nと正規化したライト方向ベクトルLの内積N·Lを計算し、一定値を境に明部と影部を切り替えます。形状に自然に追従するため、身体や衣服には扱いやすい方法です。

顔では「立体として正しい陰影」と「二次元のキャラクターデザインとして読みやすい影」が一致しないことがあります。鼻、唇、まぶた、頬には細かな法線変化があり、連続階調なら目立たない変化も、二値化すると細い影、分断された島、波打つ境界として現れます。表情でメッシュが変形すれば、境界も変わります。

『Hi-Fi RUSH』のGDC 2024講演資料では、基本的なキャラクター陰影にN·Lを用いながら、顔影はUV上のthreshold mapで制御しています。CGWORLDの制作記事でも、表情変化の大きい顔で意図した影を維持するためのFace Threshold Mapが紹介されています。

これは法線計算が誤っているという話ではありません。法線が答えるのは「この立体へ光を当てた結果」であり、顔影スレッショルドマップが答えるのは「この光方向で見せたい図形」です。

保存するのは「影の濃さ」ではなく「切替位置」

ここでは4つの量を区別します。Lは頭部のローカル座標で表した正規化ライト方向ベクトルです。φは、Lの前後・左右成分から求める水平方向の実ライト角です。

tは、制作で定めたLight StartsからFull Lightまでを0~1に正規化した制作進行度です。u(p)は、UV画素pが明部へ切り替わる正規化位置を表します。Quick SDF Paintはtを0~100%で表示します。この割合は物理的なライト角φそのものではありませんが、中央50%のSide Light 90°キーは真横方向から直接生成されます。

以下では、明部をLight状態、影部をShadow状態と呼びます。顔のUV上に画素A、B、Cがあり、tを0から1へ進める場面を考えます。Aは早くLight状態になり、Bは途中で、CはFull Lightの近くまでShadow状態に残るとします。完成テクスチャには、3つの切替位置u(A)、u(B)、u(C)を保存します。

t = normalize(φ; Light Starts, Full Light)
Light(t, p) = [ t ≥ u(p) ]

式中の[条件]は、条件が真なら1、偽なら0を返す二値判定を表します。

実装によって白黒、比較方向、0と1の意味は反転します。しかし本質は、各画素が制作進行度t上に1つの切替位置u(p)を持つことです。中間のグレーは「半分だけ明るい画素」ではなく、「その位置で状態が切り替わる画素」を意味します。影色、境界のぼかし、影の濃さは、判定後にシェーダー側で適用できます。

Quick SDF Paint 0.9.0のlilToon向け既定出力では、正規化した切替位置を反転し、16-bitの値に量子化します。

q_lilToon(p) = round((1 - u(p)) × 65535)

この反転を知らずにuとして直接比較すると明暗の進行が逆になります。出力先ごとにチャンネル、反転、比較方向を確認してください。

一般的なシャドウマップ(Shadow Map)とも役割が異なります。シャドウマップはライトから見た奥行きを使い、そのフレームにおける幾何学的な遮蔽を判定します。顔影スレッショルドマップはUVに固定された制作データであり、髪や手が顔を遮ったかどうかは判定しません。実際のシェーダーでは、顔の主要な明暗境界、リアルタイム影、AO、固定マスクを組み合わせて使えます。

制作から表示までを4段階で捉える

01 制作(Authoring)角度別マスクで意図を定義
02 補間(Interpolation)離れた境界の間を補間
03 符号化(Encoding)画素ごとの切替位置へ圧縮
04 評価(Evaluation)制作進行度と比較
角度別の二値マスクから画素ごとの切替位置を作り、任意の進行度で顔影を再構成する流れ
角度別マスクは制作入力、中央のグレースケールは切替位置、右側は任意の進行度から再構成した二値影。符号付き距離場は、入力から切替位置を求める途中でだけ使う。

1. 制作(Authoring):代表キーで望む影を決める

制作進行度t上に代表キーをいくつか置き、各キーでLightにしたい領域を白、Shadowにしたい領域を黒として定義します。法線から下描きを作っても、最初から手描きしても構いません。大切なのは、自動計算を完成結果とせず、アーティストが輪郭を直接修正できることです。

必要なキー数に普遍的な正解はありません。『Hi-Fi RUSH』の公開制作記事ではDCC上でライトを等間隔に回し、複数の二値画像を生成・修正する工程が示されています。一方、Anime Shading Plusの公開手順では9枚を例にしています。

キーを増やせば局所的な制御はしやすくなりますが、制作量と不整合の可能性も増えます。粗い間隔から始め、境界の経路を変えたい区間にだけ追加する方が管理しやすくなります。

2. 補間(Interpolation):白黒ではなく境界の移動を補う

角度キーを順番に切り替えるだけでは、影は段階的に飛びます。画像のRGB値を線形に混ぜてもグレーは作れますが、二値化した結果では差分領域が途中で一斉に反転し、輪郭が滑らかに進まない場合があります。

符号付き距離場(Signed Distance Field、SDF)を使う方法では、各マスクについて境界までの距離を求めます。隣接する2つの境界からの距離比によって、その画素が区間内のどこで切り替わるかを推定します。SDF Based Transition Blending for Shadow Threshold Mapと公開ツール実装で、この考え方を確認できます。

transition = distanceFromA / (distanceFromA + distanceFromB)

SDFは有効な補間方法ですが、このデータ表現の必須条件ではありません。入力が単純なら累積マスクなど別方式でも切替位置を作れます。SDFが担当するのは、離れた輪郭の途中位置を距離から求める部分です。

距離比の式、4方式の再現可能な比較、トポロジー変化での限界は、角度別マスクを1枚にまとめる方法:SDF距離補間の比較で詳しく扱います。

3. 符号化(Encoding):状態列を1つの値へ圧縮する

角度別マスクをM(p, t)とします。ある画素が制作進行度に沿って1回だけShadowからLightへ変わるなら、その履歴は1つの切替位置u(p)で表せます。

M(p, t) = [ t ≥ u(p) ]

複数の画像をランタイムへ持ち込まず、「いつ変わるか」だけを1枚に残せるのはこのためです。左右を別チャンネルに保存する、左右対称ならUVを反転する、といった格納方法はシェーダーごとに異なります。

4. 評価(Evaluation):頭部に対する光方向と比較する

シェーダーは頭部のローカル座標でライト方向ベクトルLを求め、顔のForwardとRightを基準に実ライト角φを計算します。さらにφを制作進行度tへ写像し、左右のどちらから光が来るかに応じてチャンネルまたはUV方向を選びます。最後に、tとテクスチャの切替位置u(p)を比較します。

頭部のローカル座標を使うことで、キャラクターや頭が回転しても、顔に対するライトの相対方向を保てます。

ほかの顔影制御とどう使い分けるか

方式によって、アーティストが直接編集する対象が異なります。以下は複数の方式を同じ評価軸で比較した、本記事独自の整理です。

顔影制御方式の比較
方式編集するもの強み主な制約
通常法線+N·L形状・法線形状と自然に連動し、一般ライティングと統合しやすい二値化した顔では細かな法線変化が目立つ
編集法線・法線転写調整した法線場追加の切替テクスチャが不要欲しい二次元境界を法線から逆算する必要がある
Proxy/平滑化法線単純化した法線場顔全体の陰影を整理しやすい鼻や頬ごとの具体的な輪郭を描きにくい
固定マスクUV上の白黒領域常に暗くする場所などを直接指定できるライトが動いても境界が移動しない
複数マスク切替角度別の完成画像各キーの形を直接確認できる画像数、段差、ブレンド時の輪郭を管理する必要がある
スレッショルドマップ画素ごとの切替位置描いた輪郭の変化を1枚にまとめられる1画素につき基本的に1回の切替しか表せない

身体や衣服の陰影まで置き換える必要はありません。形状に沿った反応が望ましい部分には法線を使い、輪郭を設計したい顔だけにスレッショルドマップを適用する構成が現実的です。

1画素1回の切替という制約

1つの閾値で表せる1方向の状態列S S S L L L L
1つの閾値では表せない往復する状態列S L S L L S L

一度Lightになった画素が後のキーでShadowへ戻る場合、その履歴を1つの切替位置へ無損失に圧縮できません。2回以上の切替が必要なら、追加チャンネル、複数のマップ、二次元の光方向データなど、表現自体を拡張する必要があります。

そのため角度別マスクは、独立した完成イラストの集まりではなく、1方向へ変化する同じ影境界として設計します。制作ツールのMonotonic Guardや書き出し時の修復は、この表現上の制約を守るための処理です。

この方式が適している条件

  • 物理的な正しさより、顔影を図形として整えて見せたい
  • 主に1つの代表ライト方向を使う
  • 頭部を基準にした左右方向の変化が重要
  • 制作進行度に沿って明部が1方向へ増減する
  • 顔に安定したUVがある
  • アーティストが法線より白黒の輪郭を直接修正したい
  • ランタイムで多数の角度画像を保持したくない

特に「各代表キーで完成形を描けること」と「ランタイムでは1枚として扱えること」の間をつなぐ点が特徴です。

1枚のスレッショルドマップだけでは扱えないもの

上下方向の大きなライト移動

水平方向だけを1つの値に圧縮した実装では、上下方向を独立して表現できません。上下にもライトが大きく動く場合は、別パラメーター、複数のマップ、通常の法線陰影との合成が必要です。

髪や手が落とす幾何学的な影

遮蔽物を見ていないため、髪が額へ落とす影や手が顔を横切る影は、リアルタイムのシャドウマップなど別の可視性計算で扱います。マップに鼻影らしい図形を描くことはできますが、それは物理的な投影ではなく、実ライト角φに関連付けたデザインです。

複数ライトと近距離のポイントライト

1つの代表方向を前提とする方式では、複数方向からの寄与を1つの閾値だけで表せません。近距離のポイントライトでは顔の場所ごとにライト方向も変わるため、頭部中心からの1方向近似には限界があります。

極端な表情変形

UVベースなので通常の表情変形には追従しますが、描いた境界自体もメッシュと一緒に伸びます。口を大きく開く表情などで対応できない場合は、表情別の補正や適用範囲マスクを検討します。

制作前に決める6項目

  1. 顔の座標系:Forward、Right、Upを明示する。
  2. 角度の意味:実ライト角φから制作進行度tへの写像、値が増える方向、白黒の意味を決める。
  3. 左右の扱い:UV反転で共有するか、左右を別データとして持つか決める。
  4. キー密度:枚数を均等に増やさず、境界の経路が変わる区間へ置く。
  5. 1方向の変化:各画素が制作進行度に沿って1回だけ切り替わる状態を保つ。
  6. 出力仕様:チャンネル、反転、ビット深度、色空間を記録する。

この6項目が曖昧だと、影形状自体が正しくても、シェーダー上では左右反転、進行度のずれ、階調劣化として現れます。

実際に使われている呼称

この分野には統一名称がなく、似た表記でも完成テクスチャ、生成方法、シェーダー機能のどれを指すかが異なります。以下は各資料・実装が実際に使っている表記であり、同義語の標準一覧ではありません。

公開資料と実装で使われている名称
資料・実装原文の表記主に指しているもの
Hi-Fi RUSH GDC講演threshold mapライト方向から求めた値と比較する完成テクスチャ
CGWORLDFace Threshold MapHi-Fi RUSHの顔影制御
ながむしメモShadow Threshold MapSDF距離比で生成する切替位置マップ
akasaki1211sdf_shadow_threshold_mapSDF補間による生成ツール
Anime Shading PlusFace Shadow Map/SDF-based face shadow mapシェーダー入力と生成工程
lilToonSDF Face Shadow/Shadow SDF modeマテリアル・シェーダー機能
PotaToonFace SDFシェーダー内の顔陰影機能
Natane Toon ShaderSDF Shadow Map/SDF Shadow Textureシェーダー機能と入力テクスチャ

本サイトでは出力の役割を示すため「顔影スレッショルドマップ」と表記し、SDFは角度別マスクの境界を補間する生成手法として説明します。Face SDFを採用する製品は実在しますが、すべての方式を指す一般名称とは扱いません。

まとめ

顔影スレッショルドマップは、完成した顔影の色を保存する画像ではありません。各画素が制作進行度tのどこでLightとShadowを切り替えるかを、切替位置u(p)として保存するデータです。

  1. 代表キーごとに望ましい白黒マスクを作る
  2. 離散した境界の移動を補間する
  3. 各画素の切替位置を1つの値へ変換する
  4. ライト方向Lから求めた制作進行度tと比較する

SDFは2番目を実現する1つの手段です。何でも解決する陰影方式ではなく、主に横方向へ変化する顔影を、アーティストが輪郭として設計するための限定されたデータ表現です。

Blender上で法線ガイドを下描きとして使う具体的な修正手順は、Quick SDF Paint 0.9.0で顔影スレッショルドマップを作る:Blenderでの実践手順へ続きます。