VATの基本原理(本チュートリアルで扱う範囲)

VATの基本原理(本チュートリアルで扱う範囲)

  • VAT(Vertex Animation Texture)は、メッシュの頂点位置(Position)・法線(Normal)・頂点カラー(Color)などを、 フレームごとにテクスチャへ格納 し、ゲームエンジン側でそのテクスチャを参照してメッシュを変形・再生する方式です。
  • テクスチャに保存された値は 補間しやすい ため、ゲームエンジン側で0〜1の時間を与えながら、滑らかに再生(補間)できます。
  • この方式により、ボーンでは表現しづらい「任意の変形アニメーション」をエンジン側で再現できます。

VATエンコードの設定(IlluGen側)

本チュートリアルでは、IlluGen付属のプリセット Blooming flowerを例に、VATへ格納してUE5で再生します。

  • フレーム範囲とストライド(Stride)
    まず、ジオメトリを VAT Encode ノードへ接続します。
    VAT Encodeは「スプレッドシートのように」開始フレーム / フレーム数 / ストライドを指定してエンコードします。
    Stride は「何フレームごとにエンコードするか」です。
    Stride=1:毎フレームをエンコード
    Stride=5:1フレームをエンコード → 4フレームをスキップ(…を繰り返し)
    例として、フレーム数を 68 に設定し、ゲームエンジン側で補間して再生できるようにします。
  • UVセット(VAT参照用UV)
    エクスポートされるメッシュは、UVのうち1セットをVAT参照用に専用化します。
    これは「各頂点がVATテクスチャ内の“自分のデータ位置”を指す」ために必要です。
    未使用のUVをVAT用に選びます。
    この例はテクスチャ未使用(頂点カラーのみ)なので UV0 を使用
    すでにテクスチャでUV0を使用している場合は、UV1/UV2/UV3など未使用のUVを使います。
  • 精度(8bit / 16bit)と split(high/low)
    VATは 8bit または 16bit で格納します。
    8bit はメモリ効率が良い一方、値の精度が下がりやすく、特に Position は精度が重要になります。
    16bit は多くの場合「これで十分」な精度を得やすく、運用しやすい選択肢です。
    8bitでPositionを扱う場合は、split(high/low)を推奨します。
    splitは、Positionを2ピクセル(high / low)に分けて格納し、合成して精度を確保します。
    この場合、Positionは1頂点1フレームあたり2ピクセルを使用します。
  • 圧縮禁止(重要)
    VATテクスチャは圧縮できません。 圧縮すると結果が大きく崩れます。
    チュートリアル内では、目安として次を述べています。
    8bit:RGBA8(相当)として扱う(圧縮なし)。
    16bit:HDR(RGBA16F等)として扱う(圧縮なし)。
  • 位置レンジ(Scale)の決定
    Positionは内部的に 0〜1の範囲へ格納され、ゲームエンジン側でScaleを使って実スケールへ戻します。
    そのため、IlluGen側で「Positionの最大レンジ(Scale)」を決めておき、UE5側でも同じ値を使う必要があります。
    Scaleは Bounding Box を見て決めます。
    例:Bounding Boxの最大が 117 → 余裕を見て 200 を採用。
  • 格納するデータの選択(Position / Normal / Tangent / Color)
    VATに格納する要素は用途に応じて選びます。
    Position:ジオメトリ変形を再生するなら基本的に必要。
    Normal:エンジン側でライティングしたい場合に有効(Emissive中心なら必須ではない)。
    Tangent:モデルがノーマルマップを使う場合に必要になることがある。
    Color:頂点カラーを再生したい場合に有効。
    チェックを増やすほど、1フレームあたりのピクセル数(データ量)が増える点に注意します。
    チュートリアル例では、NormalColorを使っています(Positionはsplit)。

エクスポート(モデル / VATテクスチャ)

  • 出力の構成
    出力は大きく2つです。
    Export Model(メッシュ)
    Export Texture(VATテクスチャ)
  • First Frame(開始フレーム)の注意
    モデルとテクスチャの First Frame は「エンコード完了後」に設定します。
    例として、エンコード処理が 360付近まで進むため、First Frameを 360 に設定しています(ModelもColorも同様)。
  • Unreal向けの設定(単位 / sRGB)
    Unrealへ持っていく場合、メッシュは cm(centimeters)で出力します。
    VATテクスチャ(Color側を含む)は、sRGBをオフにしてLinearで扱う方が良いとしています(精度問題を避けるため)。
    ここで、テクスチャを 8bit/16bit のどちらで保存するかも選びます。
    split + 8bit運用なら 8bit
    single + 16bit運用なら 16bit
  • 命名(例)
    例として、出力名を次のように分けています。
    メッシュ:mesh_mesh
    テクスチャ:mesh_vat

出力テクスチャの見方(構造)

  • テクスチャは自動的に「最適サイズ」が選ばれ、例では 2K × 1K になっています。
  • テクスチャの構造は次の通りです。
    幅(横)=フレーム数(例:68px幅=68フレーム)
    縦方向=頂点が並ぶ(例:頂点数 7,592)
    行(ライン)=データ種別
  • split Position + Normal + Color の例では、合計4ラインを使用します。
    1〜2行目:Position(split / high+low)
    3行目:Normal
    4行目:Color(色が見えているライン)


UE5:インポート〜再生

メッシュのインポート(Nanite無効)

メッシュは通常のパイプラインでインポートできます。
ただし、Naniteビルドは無効化します。
Naniteが有効だと、頂点が飛ぶ(flying vertices)現象が出るため、VATでは避けるべきとしています。

VATテクスチャのインポート設定(圧縮なし / sRGBオフ / Never Stream)

8bitテクスチャの場合、Unreal側で圧縮を完全に外す必要があります。
例では次の設定を行っています。
Compression Settings:User Interface(RGBA8)(圧縮を避ける)
sRGB:オフ(Linearとして扱う)
Streaming:Never Stream:オン(ストリーミングが原因と思われる不具合回避)。

テンプレートマテリアル → マテリアルインスタンスで動作確認

  • チュートリアルでは、VAT用に提供されているテンプレートから Material Instance を作ります。
  • 今回のデータ構成は Position(split)+ Color なので、親はそれに一致するものを選びます。
    例:VAT_split_pos_col_mat(表記はプロジェクト側の命名に準拠)
  • インスタンス側で設定する主なパラメータは次の通りです。
    Frame Count:68
    Scale:200(IlluGen側で決めた値)
    VAT Texture:書き出したVATテクスチャ
  • オブジェクトへ適用すると、VATアニメーションが再生されます。

表示欠け(片面表示)の修正:2-sided化

症状

  • 動作自体は正しいが、メッシュが Two Sided ではないため、面が欠けて見える(ワイヤーフレームで欠けが確認できる)状態になります。

対応:提供マテリアルを複製して自分用に調整

  • 提供マテリアル群から、今回必要な構成(split pos + color)に近いものをコピーし、自分用に作り直します。
  • 参考として、最も全部入りの例は以下です。
    split position / normal / tangent / color を含むもの。
  • 今回は position+color だけ必要なので、該当テンプレを複製して調整します。

マテリアル内部の要点(デコード):2-sided化

UV Set(VAT参照UV)

  • 提供マテリアルはデフォルトで UV1 を参照する作りですが、今回のメッシュはUVセットが1つ(UV0のみ)なので、どれを指定しても同じに見える場合があります
  • 運用として「正しく合わせる」なら、UV Set を 0 に揃えます

再生時間:Normalized Time(0〜1)

  • アニメーションは Normalized Time(0〜1) で駆動します。
  • 外部(Blueprint等)から制御したい場合は、Normalized Timeへ Scalar Parameter を挿し、0〜1の値を渡します
  • 値の範囲が不安なら Saturate を挟み、0〜1に収めます。

VAT Decode Function と Data Index(行の指定)

  • VAT Decode Function は、テクスチャからデータを読む中核です。
  • 入力として次を渡します。
    UV Set
    Normalized Time
    Texture Object
    Frame Count
    Data Index(重要)
  • Data Index は「どの行(ライン)を読むか」を示します。
    行の順番は基本的に固定で、次の並びです:
    Position → Normal → Tangent → Color
  • split Position の場合、Positionは 0行目と1行目を使います。
    今回は(split position + color)なので、Colorは次の行=2 になります。

Positionの復元(WPO)

  • Positionの復元は方式で分岐します。
  • splitの場合:VAT Decode Position Split
    16bit singleの場合:VAT Decode Position
  • splitの場合は high/low を合成し、Scale(例:200)でリスケールして、
    結果を World Position Offset へ接続します。

Colorと Vertex Interpolator(必須)

  • Colorは基本的に「そのまま使える」データですが、Vertex Interpolator が必須です。
  • これが無いと、UVが補間された結果で色を参照してしまい、見た目が破綻します。
  • チュートリアルでは、Colorを Base Color に送っています。
    用途により Emissive に送ることもできます。

Two Sided と Shading Model の調整

  • 表示欠け対策として、マテリアルを Two Sided にします。
  • Shading Modelも必要に応じて変更できます。
    例:Two Sided Foliage
  • Thin Translucentを使う場合はTranslucentが必要になり、
    今回の用途では「良くない」としています。
  • Two Sided Foliageにして、Colorを Subsurface Color に送ると、
    見え方(ライティング)が改善する場合があります。

まとめ(このチュートリアルで揃えるべき項目)

まとめ(このチュートリアルで揃えるべき項目)
  • IlluGen側で決めた値(例:Frame Count=68 / Scale=200 / UV0)を、
    UE5側でも一致させます。
  • UE5側は Nanite無効 / 圧縮なし / sRGBオフ / Never Stream を徹底します。
  • Data Indexは「読む行(ライン)」で、順番は
    Position → Normal → Tangent → Color(欠けはスキップ)です。
  • Colorは Vertex Interpolator必須、表示欠けは Two Sided で解決します。