Character animation

Vertex Animation Textures / VAT

頂点アニメーションテクスチャ

頂点の動きを画像へ焼き込んで再生する。

10 / 10

Interactive demo

Preparing the demo…

Vertex Animation Textures / VAT

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

メッシュの頂点の動きをあらかじめ全フレームぶん計算し、画像(テクスチャ)の画素として焼き込んでおき、描画するときに頂点シェーダーがその画像から自分の位置を読み出して再生する方法です。骨の計算(スキニング)も物理計算も実行時にはいらないので、何千体ものキャラクターや、複雑な破壊・流体の動きを、とても軽く再生できます。

ゲームでの使いどころ

  • 群衆:スタジアムの観客、戦場の兵士、街の人々。GPU インスタンシングと組み合わせ、1 回の描画命令で数千体を動かします。
  • 魚群・鳥の群れ・虫:単純な泳ぎや羽ばたきを大量に。
  • 事前計算した物理:建物が崩れる、旗がはためく、水がはねるといった、リアルタイムでは重いシミュレーションを Houdini などで計算して焼き込み、ゲームでは再生だけする。
  • 遠景のキャラクター:近くはスキニング、遠くは VAT、という LOD の使い分け。

しくみ

  1. 焼き込み(オフライン):アニメーションの各フレームで、メッシュの全頂点の位置(と法線)を計算し、画像の 1 行に並べます。

    • 横方向:頂点の番号(頂点が 1344 個なら幅 1344)
    • 縦方向:フレームの番号(24 フレームなら高さ 24)
    • 画素の色:頂点の位置 (x,y,z)(x, y, z) を RGB に入れる(浮動小数点テクスチャ、または範囲を決めて 16 ビットに量子化)
  2. 頂点に番号を持たせる:各頂点に「自分の番号」を属性(または UV の空きチャンネル)として持たせます。

  3. 再生(実行時):頂点シェーダーで、今のフレーム番号と自分の頂点番号から画像の座標を計算し、位置を読み出して頂点を動かします。前後 2 フレームを読んで線形補間すると、少ないフレーム数でもなめらかです。

p=lerp(tex(i+0.5Nv, f+0.5Nf),  tex(i+0.5Nv, f+1.5Nf),  frac(f))\mathbf{p} = \text{lerp}\Big(\text{tex}\big(\tfrac{i + 0.5}{N_v},\,\tfrac{f + 0.5}{N_f}\big),\;\text{tex}\big(\tfrac{i + 0.5}{N_v},\,\tfrac{f + 1.5}{N_f}\big),\;\text{frac}(f)\Big)
  1. ばらけさせる:インスタンスごとに再生の開始位置(オフセット)や速さを変えると、全員が同じタイミングで動く不自然さがなくなります。

法線も同じように焼き込むか、変形の少ない動きなら元の法線を使います。

実装のポイント

  • テクスチャの形式:精度が必要なら RGBA の 16 ビット浮動小数点(half float)を使います。8 ビットに量子化する場合は、位置の範囲(バウンディングボックス)を別に保存して戻します。
  • 頂点数とテクスチャサイズ:テクスチャの幅には上限(多くの環境で 4096〜16384)があります。頂点が多い場合は複数の行に折り返して格納します。
  • フィルタは最近傍:隣の頂点の値が混ざらないよう、テクスチャのフィルタは NEAREST にし、補間はシェーダーで行います。
  • 複数のアニメーション:歩き・走り・待機など複数の動きを、1 枚のテクスチャに縦に並べ、開始行と長さで切り替えます。
  • 骨を焼き込む方式:頂点ではなく骨の行列を焼き込み、シェーダーでスキニングする方式(ボーンアニメーションテクスチャ)もあります。こちらは頂点数によらずテクスチャが小さく済みます。

つまずきやすい点

  • メモリが大きい:頂点数 × フレーム数 × 画素のサイズになるので、長いアニメーションや高密度のメッシュではすぐに数十 MB になります。フレーム数を減らして補間する、遠景用に頂点を減らしたメッシュで焼く、などで抑えます。
  • 動きの切り替えが苦手:焼き込んだ動き以外はできず、ブレンドや IK も基本的にできません。主役には使わず、背景や群衆に使います。
  • 影と当たり判定:影を描くための深度用のシェーダーにも同じ頂点の読み出しを入れないと、影だけ動かなくなります。当たり判定は元の形のままなので、大まかな形状で代用します。

デモで試すこと

  1. 800 匹の魚が、すべて 1 回の描画命令で泳いでいます。上に表示している画像が、1 匹分の泳ぎを焼き込んだものです。横が頂点、縦がフレームで、色は頂点の位置です。
  2. 「焼き込むフレーム数」を 4 に下げると、泳ぎがぎこちなくなります(フレーム間は補間していますが、動きの形が粗くなる)。画像の縦の長さも短くなります。
  3. 「魚の数」を 1500 に上げても、骨の計算をしないので、ほとんど重くなりません。
  4. 「泳ぐ速さ」を変えると、画像を読む速さが変わり、尾びれを振る速さが変わります。魚ごとに読み始めの位置をずらしているので、全員が同じ動きでもそろって見えません。

References

Unreal Engine IK Rig Solvers ↗

A general reference for this subcategory.