Help us understand the problem. What is going on with this article?

DirectX11シェーダーでVertex Animation Texture

More than 1 year has passed since last update.

Maya Advent Calendar 2018 12月24日の記事です。
クリスマス・イヴ、皆様どうお過ごしでしょうか?
私は残念ながら風邪でダウン…

この投稿が皆様の一助となれば幸いです。

Vertex Animation Textureとは?

Vertex Animation TextureはVATと略して呼ばれることが多いです。

テクスチャに位置や法線の情報を保存しておき再生するようなものです。
複数のモーフターゲットをテクスチャの中に保存できると思えばわかりやすいです。

テクスチャへのデータ保存について

VATそのものは難しいことをしているわけではありません。

一例です。
たしかHoudiniのリジッドボディー?か何かは以下のような保存だった…気がします。

  • Rチャネル には 位置X
  • Gチャネル には 位置Y
  • Bチャネル には 位置Z
  • Aチャネル には 法線

Aチャネルの法線ですがfloat3からfloatに変換して保存する必要があります。
利用するときはfloatからfloat3に戻して利用します。
pack/unpackとか呼ばれるようです。
「float3 to float pack」とかで検索するといろいろ出てきます。

pack/unpackに関しては今回の記事では触れませんが、以下の資料が参考になります。
CEDILにログインすることで、資料を閲覧することができます。

シェーダの工夫で超えられる表現の壁がある! -ゲームエフェクトにおけるトリッキーなシェーダ講座-

VATというのはテクスチャに入れたい情報を入れて再生する技術です。

なので、自分でOpenCV等のライブラリから作ってもいいかもしれません。
私はPySideのQImageで自作しました。8bitだったので精度は出ませんが…。

Mayaで再現する

Mayaで再生する方法はいくつかあります。

・MPxDefomerNode
Mayaのデフォーマーノードプラグインを作ります。
これは結構面倒くさいのでおすすめはしません。

・DirectX11Shader
シェーダー側で作れば割と簡単に作ることができます。
今回はDirectX11シェーダーで作ってみます。

利用したポリゴンメッシュとテクスチャ

今回は三角形のポリゴン1枚を使います。三角形なので頂点が3つ存在します。
アニメーションは3フレームを利用して作ってみます。

3頂点 ✕ 3フレーム = 9ピクセル
が必要になります。

SimpleVAT_Scale.jpg
※ 画像はわかりやすく大きくしているものです。3×3ピクセルと思ってください。

情報は以下のように処理されます。

フレーム番号
フレーム 0 頂点ID 0 頂点ID 1 頂点ID 2
フレーム 1 頂点ID 0 頂点ID 1 頂点ID 2
フレーム 2 頂点ID 0 頂点ID 1 頂点ID 2

例えば、
・フレーム0 の時は頂点ID0に入っているのは赤(RGB:1,0,0)
・フレーム0 の時は頂点ID1に入っているのは青(RGB:0,1,0)
・フレーム0 の時は頂点ID2に入っているのは緑(RGB:0,0,1)
入っている値をオフセットさせてみます。

コードサンプル

以下がコードの全てです。
VertexAnimationTextureをシェーダーで作るの大変そう…
と思いきやLoad関数で一発です。

float4x4 g_WXf : World;
float4x4 g_VXf : View;
float4x4 g_PXf : Projection;

uniform int g_Location;
Texture2D g_VATexture;

struct VS_IN
{
    float4 Pos : POSITION;
    float2 TextureUV  :TEXCOORD0;
};

struct VS_OUT
{
    float4 HPos : SV_Position;
    float3 VATColor :TEXCOORD1;
};

VS_OUT VS(VS_IN In)
{
    VS_OUT Out = (VS_OUT)0;
    float3 w_pos = mul(In.Pos, g_WXf).xyz;
    float3 vat_pos = g_VATexture.Load(int3(int(In.TextureUV.x),g_Location, 0)).xyz;
    w_pos = w_pos + vat_pos;
    Out.HPos = mul(mul(float4(w_pos,1.0), g_VXf), g_PXf);
    Out.VATColor = vat_pos;
    return Out;
}

float4 PS(VS_OUT In) : SV_Target
{
  return float4(In.VATColor, 1.0);
}

technique11 VertexAnimationTexture
{
  pass p0
  {
      SetVertexShader(CompileShader(vs_4_0,VS()));
      SetGeometryShader(NULL);
      SetPixelShader(CompileShader(ps_4_0, PS()));
  }
}

注意点

今回、SV_VertexIDのセマンティクスを使うとMayaが落ちる事態になったので
頂点IDはUVに入れました。
ちなみにHoudiniからの出力もUVで出力されていますが、
頂点IDのセマンティクスが使えればそっちの方が楽かもしれません。

結果

わかりやすく、カラーに変位を入れてみました。
g_Location変数がフレームです。こちらを変更すると以下のような結果が得られます。

SimpleVAT_Conclusion.jpg

おわりに

VertexAnimationTextureの再生方法を紹介しました。

私的なことですが、
個人サイト リグログ を今年いっぱいで閉じます。
長らく見て頂いた方、ありがとうございます。
今後は別のサービスを利用して情報発信は継続していこうとは思っています。

それでは!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away