制作での躓き2(スキンメッシュの不自然な陰)
FPSの制作中に躓いたことのお話2回目です。
3DCGの技術的な解説になります。
なお個人の分析によるものなので勘違いもありうる事をご了承下さい……
unityでキャラをジャンプさせての落下中に、胸の下に不自然な陰(影)があるのを見つけました。
あごの下と比べると分かりますが明らかに暗すぎます。
光源の向きを色々変えてみたところ、変な方向で少し明るくなったりする……?
どうやら法線がおかしいようです。
法線とは面に垂直な線のことで、法線ベクトルとしてベクトルで扱われ、3DCGではこれを使って面がどちらを向いているか判断して陰影をつけています。
なぜ法線がおかしくなっているのか?
どうも、おっぱいが下に垂れている元の状態から法線が変わっていないような感じです。
ちなみにおっぱいはボーンで動かしています。
では腕など他の所は曲げると陰影が変わるのに、胸の下だけ変わらないのは何故なのか?
それは法線がボーンの回転によって変わっていて(当たり前ですが)、
胸の下の変形はボーンがほとんど回転していなかったからです。
まずunityのようにリアルタイムでレンダリングされる3DCGでは、
メッシュの頂点に保存されている法線ベクトルを参照して面の向きを判断しています。
左図のように腕などではボーンと一緒にポリゴンと法線も回転し、
回転する所としない所の境は補間された法線の向きになると思われます。
対して胸部分では、おっぱいを平行移動のように動かしたかったので、ボーンの根元を背中の方まで伸ばしてあり、おっぱいが大きく動いてもボーン自体はあまり回転していません。
なので法線の向きもほぼ変わりません。
しかしポリゴンの面の向きはボーンで動く頂点(おっぱい)と動かない頂点(胸板)があることで大きく回転しています。
実際の面の向きと頂点に保存されている法線の向きが違っているので、
不自然な陰ができてしまうのです。
原因は分かりましたが、ではどうやって間違った法線の向きを変えればいいのでしょう?
法線を再計算する方法がありますが、毎フレーム行わなければいけないので重そう……
しかもunityの関数だとUVの継ぎ目で滑らかに出来ないみたいです。
シェーダーでやるのも難しいし色々大変そう……
他に方法はないものか?
少し話が戻りますが、なぜ陰ができるか探っている時にたまたま、ボーンではなくブレンドシェイプで同じ形に変えると正しい陰影になるという事を見つけていました。
ブレンドシェイプは頂点の移動ベクトルと、移動後の法線ベクトルを保存しているので正しく陰影ができるのです。
しかしブレンドシェイプは回転に不向きでおっぱいの先の方の動きが良く表現できません。
じゃあ移動値を使わずに法線ベクトルだけを、おっぱいボーンの回転に合わせて反映できれば……
と思ったら都合よくそれができるツールを発見しました!
「Blend Shape Builder」
unity上でブレンドシェイプの作成・編集ができるツールです。
これでおっぱいが上がったブレンドシェイプの移動値を消して法線ベクトルを残した物を作り、
ボーンの回転に合わせてそれを増減させれば正しい陰影になる訳です。