こんにちは
簡単に自己紹介します。株式会社たき工房 でプログラマーをしていて、個人ではTouchDesignerで映像制作やVJをしています。その他、TouchDesignerのもくもく会を月に1回開催しています。
komakinex:Twitter
TouchDesignerもくもく会など:Peatix
今年のアドベントカレンダーの1日目にOpenCVの記事を書いたのでよければ見てください!
TouchDesignerでOpenCVを使った簡単な顔認識について
今回は大量の物体をアニメーションさせることについての記事です。
ちょうど一年くらい前に、Hiroyoshi Murataさんのツイートでたくさんの人がバラバラに動いているのを見ました。
20190104#TouchDesigner #creativecoding pic.twitter.com/M4bxnHkOQD
— Hiroyoshi Murata (@muracchijp) January 4, 2019
単純なインスタンシングだと、どのモデルも同じ動きになってしまうので自然な表現とは言い難いです。
リプ欄を見てもらうとわかりますが、丁寧に教えていただきました。ただ、どういう仕組みで動いているのかなんとなくわかったのですが、実際に自分で作るとなると全然わからないままでした。
それから月日が経ち、VJで使ってみたいなと思い、村田さんの言葉を頼りに色々と調べて実装してみました。
Vertex Animation Textureとは
先程のアニメーションの手法を頂点アニメーション、Vertex Animation Textureといいます。簡単にいうと、頂点数×アニメーションのフレーム数の解像度の画像に、頂点の位置情報(xyz座標)を色情報(RGB)として持たせて、その画像をシェーダで順番に読み取ることでモデルの頂点を動かすことです。
以下の記事が参考になりました。
・インディーゾーンHoudini情報日本語ブログ - Vertex Animation Texture について
・土屋つかさの技術ブログは今か無しか - 頂点アニメーションとはなにか
・サルにもわかる Houdini - Vertex Animation Texture Unreal
・テラシュールブログ - 【Unity】シェーダーで3Dモデルのアニメーションを行う Animation Texture Baker
Vertex Animation Textureでモデルをアニメーションさせる一連の流れのことを、この記事ではVATと略すことにします。
出来上がり
クリスマスフェス! #TouchDesigner pic.twitter.com/2vnlRgR7rF
— komakinex (@komakinex) December 25, 2019
かなりたくさんの人を、各々のタイミングでジャンプさせることに成功しました。
サンプルファイル
↓ここにあります↓
https://github.com/komakinex/TD_AdventCalendar2019_VAT
動作環境
TouchDesigner 099 2019.20140
Windows10
準備
用意するもの
・TouchDesigner
・動かしたいモデル(alembic形式)
・Houdini
Apprenticeでも問題なく進められますが、レンダリングすると画像にウォーターマークが追加されるので、VATでアニメーションさせたとき一瞬変になります。
サンプルファイルにはどっちも入っています。
この記事ではフリーの人型モデル(obj形式)にmixamoでアニメーションをつけています。その場合追加で以下が必要です。
・Adobeアカウント(mixamo用、無料で登録できます)
・Blender
流れ
・mixamoでモデルにアニメーションをつけ、fbx形式で書き出す
・それをBlenderでabc形式で書き出す
・それをHoudiniで読み込んで、Vertex Animation Textureを書き出す
・TouchDesignerでGLSL MATを使って動かす
説明
動かしたいモデルがすでにabc形式の人は①と②を飛ばしてください。サンプルファイルを開きながら見てもらえるとわかりやすいと思います。
①mixamoでアニメーションをつける
ログインして、説明通りモデルをUploadして進めていきます
気に入ったアニメーションを見つけたらダウンロードします。どこも変更せずに大丈夫です。
②Blenderでabc形式で書き出す
①で書き出したモデルをインポートします。
Blenderの画面右下のEnd
のフレーム数を、mixamoでつけたアニメーションと同じ数字にします。さっきのジャンプは97フレームのアニメーションでした。
その後、alembic形式でエクスポートします。
③HoudiniでVertex Animation Textureを書き出す
VATのためにGame Development Toolsetが必要なのでインストールします。
Shelves→Game Development Toolsetにチェックを入れ、Update Toolset→Updateをクリック、Successが出たらHoudiniを再起動します。
モデルの準備をします。Alembic SOP
に②のモデルを読み込み、TouchDesignerに合わせるためFrames Par Second
を60にします。数字を打ち込んでも30に戻ってしまう場合Frames Par Second
をクリックして、写真のようにテキストフィールドが伸びた状態で入力すると変更できます。
フレームあたりの時間を2倍にしたので、全体のフレーム数を2倍にします。右下に97×2である194を入力します。再生して、アニメーションがちゃんと最後まで流れるか確認します。
Alembic SOP
のinfoを見てみるとPacked Alembics
が1になって、頂点やプリミティブなどが1つにまとめられていたので、Convert SOP
でポリゴンに変換します。なってなければこのノードは不要です。
最後にNull SOP
を繋ぎ、わかりやすいように名前をOUT
に変えます。ここで一旦ファイルを保存します。保存しておくとVATがわかりやすいところに生成されます。
VATの書き出しに移ります。Game Development ToolsetのシェルフからVATをクリックすると、out
の階層にGameDev Vertex Animation Texture
が生成されます。
Export Node
に先ほどのOUT
を選択し、Target Texture Size
にモデルの頂点数を入力します。この数値はVATの横幅に相当します。
Normalize Data to 0-1 space
のチェックを外し、Pack Normal into Alpha
にチェックが入っていれば、写真右上のRender
をクリックします。するとファイルと同じ場所にexportフォルダが生成され、モデルとVATが入っています。
④TouchDesignerでVATする
サンプルファイルのbase
を見てください。
使うモデルはBlenderで書き出したAlembicのモデルでも、HoudiniでVATを書き出した時のoutput.abcのどちらでも構いません。BlenderでAlembicを書き出すと法線方向が変になっていたので、Attribute Create SOP
のCompute Normals
をON
にしています。
モデルに頂点の番号の情報を持たせたいので、Point SOP
を用いてCustom Attrib
にpt
を追加しています。
では、GLSL MAT
の内容に移ります。
uniform sampler2D uVAT;
uniform int uFrame;
uniform int uFrameSize;
uniform float uScale;
in int pt;
void main()
{
vec3 vP = texelFetch(uVAT, ivec2(pt, int(uFrame) % uFrameSize), 0).xzy;
vec4 worldSpacePos = TDDeform((P + vP) * uScale);
gl_Position = TDWorldToProj(worldSpacePos);
}
フレームごとに、テクスチャから読み込んだ位置を各頂点に足すことでアニメーションさせています。Houdiniで書き出されたVATはUE4向けで、座標系がTouchDesignerと異なります。Y軸とZ軸の入れ替えが必要なのでxzy
となっています。
これをインスタンシングします。サンプルファイルのinstancing
を見てください。
オペレーターの組み方はbase
と同じです。
uniform sampler2D uVAT;
uniform int uFrame;
uniform int uFrameSize;
uniform float uScale;
in int pt;
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main()
{
vec3 vP = texelFetch(uVAT, ivec2(pt, int(uFrame + gl_InstanceID * 1000 * rand(vec2(gl_InstanceID, 100))) % uFrameSize), 0).xzy;
vec4 worldSpacePos = TDDeform((P + vP) * uScale);
gl_Position = TDWorldToProj(worldSpacePos);
}
コードも基本はbase
と変わらないですが、モデルのアニメーションがずれるようにランダムな数値を返す関数を用います。インスタンシングされたモデルたちの固有値gl_InstanceID
を用いて、アニメーションの再生に関わるuFrame
にオフセットがかかるようにしています。オフセットが大きければ大きいほどアニメーションにばらつきが出るので1000
をかけています。
以上で説明を終わります!冒頭のツイートにあった、たくさんのカラフルな人がジャンプしているサンプルがsample
にあります。気になった人は見てください。
注意点
複数のCGソフトを横断する時、問題になるのが座標系とスケールです。
④で軽く触れましたが、Houdiniで書き出されたVATはUE4向けです。UE4はZ軸が上向き、
TouchDesignerとHoudiniはY軸が上を向いています。
座標系は違うのに各軸の色が揃っているのは面白いなあと思いました。
またスケールについて、今回の説明ではややこしくならないように触れなかったのですが、Blenderでabc形式に変換する時、fbxをインポートするとスケールが0.01になっています。(BlenderもZ軸が上向きで、自動で90度回転されています。)
0.01された状態が、元のfbxと同じ大きさなのでそのままにしていました。
スケールが食い違うとどうなるのか
アニメーションに対してモデルが大きいと、みんな控えめになったり
なんのこっちゃわからんくなります。
参考文献
Syuya(向井 秀哉) - 【UE4】VATの作り方と使い方 ~VATで桜を咲かせる~
UE4向けにHoudiniでVATを書き出す流れが丁寧に書かれています。
映像音響処理概説 2018 - 夏休み
比嘉さんが公開している、東京藝術大学の授業の資料にVJのプロジェクトファイルがあります。
その中の、Main.toe→WORK→Scenes→camera_button7(birds)→scene→Birdに、アニメーションする鳥がVATでインスタンシングされています。
ランダムな値を返す関数 on GLSL
GLSLでランダムな値を扱う関数について書かれています。
The Book of Shaders - ランダム
これもランダムについてです。
ks - 軸の話 〜3DCGにつきものの座標系の違い43種まとめ〜
めちゃたくさんのCGソフトの軸について書かれています。
最後に
理論的には頂点情報以外もテクスチャに書き込むことができるので、発展させるともっといろんなことができるようになると思います。一年前は全然わからなかったことを、記事することができて嬉しいです!よくわからないところがあれば聞いてください。間違っているところがあれば教えてください!
告知です!2020年1月22日にたき工房でTouchDesignerのもくもく会を、1月29日にアウトプット会を開催します。もくもく会は今までと同じように各自もくもくする会で、アウトプット会はもくもく会でやったことからTouchDesignerを使った事例紹介まで、ライトニングトークみたいな感じにしたいと思っています。
もくもく会 #2のチケットはこちら→https://techlab-tdmokumoku02.peatix.com
今後もイベントの予定は、自分のTwitterアカウントからアナウンスするので、チェックしてみてください!
Peatixをフォローしてもらえると、チケットがオープンした時に通知が行きます。
→https://techlab-tdmokumoku.peatix.com/
おまけ
まったく関係ないですが、今年のM-1も非常に白熱した戦いでした。またそれとは関係なく、蛙亭のコントが面白いのでぜひ見てみてください!
https://youtu.be/1vR_bov1Rz0
それではみなさん、よいお年を!