30
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TouchDesignerAdvent Calendar 2022

Day 13

Houdiniと連携したVJのネタ作り

Last updated at Posted at 2022-12-12

こちらはTouchDesigner Advent Calendar 2022の13日目の記事です。

MUTEK

2022/12/09にMUTEKで映像をしてきました。

MUTEKはカナダ発の電子音楽のフェスティバルで、世界中で開催されています。
そちらの日本版が渋谷ストリームホールや渋谷Wombなどで5日間に渡り開催されておりました。

対戦相手のミュージシャンはMars89さん。
極太の低音やダークなアンビエントで攻め攻めの音楽を作っている方です。

当日はこんな感じでチケットは完売。
Santaさんがたくさん上げてくれたのでお借りします。
リンク先には4本あるよ。

今回はソロではなくHEXPIXELSでの映像演出でした。
HEXPIXELSは比嘉了さんと一緒に数年やっているユニットで、
色んなDCCツールやプログラミングを駆使したリアルタイム映像を得意としています。

HEXPIXELSのシステムに関してはこちらが詳しいです。
https://www.mouse-jp.co.jp/creator/ss/daiv/case_study/hexpixels.html

ざっくり書くと、

  1. オーディオ解析結果の同期
  2. 3Dカメラ情報の同期
  3. CG上での空間のルールを決めてネタを作る
  4. 1,2,3を踏まえて作ったネタを、2台のPCから同時に出してミックスする

という点が重要です。

普通に複数人でVJをすると、様々なネタをVJミキサーでカチャカチャ切り替えるカット演出になりますが、
HEXPIXELSでは、2台のコンピュータでお互いが自由なタイミングでネタを出し入れしても、ワンカメラでの演出が可能になります。
初見では1台のPCで普通に出しているように見えると思いますが、
今回は僕はTD、比嘉さんはUE5での制作でした。

ネタ概要

さて、今回の空間ルールは、半径300メートルの半球の中心に、半径5mの半球がある、というルールでした。
半球ドーム自体の形状を変えたり、そこから何かが広がったり的な感じです。
何故このルールにしたのかは、色々と長くなるので割愛。

僕パートの映像だけ少し置きます。
半球ドームネタを中心に、周りに色々な物がおります。
何かビカビカやビクビクしてるのは内部的には音反応してるからです。

で、終演後にお客さんから、何をどうやって作ってるのか何か書けや、と囲まれたので書きます。

まず、本番の僕のUIですがこんな感じです。汚いねえ。
ボタン1個につき1ネタがオンオフ、下部はポストエフェクト系が刺さっています。

SnapCrab_NoName_2022-12-12_17-14-59_No-00.png

というような感じでしたが、全部解説したら疲れてしまうのでピックアップして書きます。

ワークフロー

ざっくり説明すると、

  1. Houdiniでモデリング
  2. 必要なアトリビュートを仕込んだモデルをbhclassicで書き出し
  3. TouchDesignerで2を動かす

みたいな感じです。

まずはHoudiniで、300mと5mの球体を置きます。
その際に空間を何となく仕切った方がネタが作りやすいので、
ガイド線を引きます。これが無いと何をして良いかわからなくなりがちです。

SnapCrab_NoName_2022-12-12_17-50-28_No-00.png

また、人のモデルも置いておきます。
これがこの世界の物の大きさの指標になります。
商品説明とかだと良くタバコとか置いてますよね。あれと同じで良く知っているものが画面にあると各物体のスケールがわかります。
これがないと、どれだけ大きいものを置いても大きく見えない。

SnapCrab_NoName_2022-12-12_17-52-5_No-00.png

あとはガイド線に沿ってネタを配置していきます。
半球を支えるおじさんなどのクライマックスネタもここで位置と大きさを決めます。

SnapCrab_NoName_2022-12-12_17-58-49_No-00.png

カメラの位置を変えながらネタを作っていきます。

SnapCrab_NoName_2022-12-12_18-3-2_No-00.png

Houdiniからの書き出し

ここでレイアウトしたものをTDに持っていくわけですが、円上に同じものを配置、とかだと
1個だけ書き出して、TDでインスタンシングした方がデータが軽くて良いです。
Houdiniでアニメーション付けとレイアウトスケッチ、物量はTDで増やす
というのを最近良くやってます。

例えば、関節系のアニメーションは、HoudiniのKineFXというリグ回りのツールで動かします。
リグを入れるだけではなく、関節を適当にノイズで動かしてね、みたいなことも可能です。
これをある程度の長さのループモーションにしてVertex Animation Texture(VAT)で書き出します。
Vertex Animation TextureとTDに関しては星野さんのこちらの記事が詳しいです。

ezgif.com-gif-maker.gif

TDではアニメーションの再生位置を少しずらしながら、円上に配置し直してます。

ezgif.com-gif-maker (1).gif

よく見ると輪郭が光っています。
これは音楽の低域に反応させています。
また、色も常に変わっているのですが、
これは中域が入った時だけ少し早く変わるようにしています。
VATの再生処理+上記の処理をシェーダーで書きます。

シェーダー書きは比嘉さんのShader Builderを使います。
ShaderBuilderは、いわゆるメタルラフネス式のPBRマテリアルを実現すると共に、
シェーダーステージ毎にブロック分けして書いたコード(CodeBlock)を組み合わせて使うので、
シェーダーの再利用が容易になります。
皆もっと使いましょう。

SnapCrab_NoName_2022-12-12_20-3-26_No-00.png

余談

こういう感じで、音に対する即時的な動きと、間接的な動き、指先などの自動的な動きなど、
動きのレイヤーを意識して作ると楽しいです。

また、一度、VATや音反応、色替えのコードを仕込んでしまえば、
CodeBlockをコピペしたら大体動くので楽です。
もちろん色替えの速度やら、追加で挿すディティールようのノイズやらはネタごとに変えてチューニングします。

VJはネタの消耗戦なので、
動きに限らず、インスタンシング用のCHOPなども、
コピペで色んな仕組みを転写できるようにしとくと良いです。
大事なことなので2回言いました。

使い回せるtoxにしろや、というツッコミも予想されますが、
ノイズ関数などの汎用的なもの以外は全ネタで変わるので、
コピペしたものをベースに編集していく、というのがまあまあ楽です。

もう少しネタの話 + 疑似コード

上記みたいな感じでたくさんネタを作っていくのですが、
反響のあった頭の煮凝りの作り方。

まず頭をHoudiniのVellumでギュっとします。
VellumはHoudiniで布とかソフトボディを作る時の仕組みです。

ezgif.com-gif-maker (2).gif

次にフレームの23フレ目と24フレ目だけ抜き出します。
ezgif.com-gif-maker (3).gif

23フレ目のメッシュだけをTDに持っていくんですが、この時24フレ目の頂点座標と法線をrestP, rnmlというアトリビュートで23フレ目のメッシュに入れておきます。
何がしたいかというと、この後TDで2つの形状をリアルタイムに行ったり来たりするためです。

ついでに各頭ごとの重心をcenter、そのメッシュが目かどうかを判定する用にeyeを作っておきます。

2022-12-12 18-48-35.mp4_snapshot_00.09.200.jpg

bhclassic形式で書き出すと、fbxと違って何でもTDに持っていけて便利です。

TDではPとrestP、Nとrnmlを音に合わせて行ったり来たりするシェーダーを書きます。
ただ、そのままオーディオのピークに合わせて一気に動かすと、単に頭全体が膨らむだけで面白くないので、
行ったり来たりするための補間の値を、centerをシード値に使ったノイズを入れて、各頭ごとにタイミングをずらす、ということをします。

// vertx shader
//uSpeedは中域が入ると早く動くような値

float l = TDSimplexNoise(uSpeed * 1 + geom.center * 100) * 0.5 + 0.5;

geom.P = mix(geom.P, geom.restP, l);
geom.N = mix(geom.N, geom.rnml, l);

// 先ほどの手と同じアプローチ。頭ごとの色をアニメーションさせたい
float c = TDSimplexNoise(uTime.y * 0.1 + geom.center * 100) * 0.5 + 0.5;
c = pow(c, 3.0);
geom.Cd.rgb = vec3(c);
//fragment shader

// 低域の値でスケールしたフレネルの値をbaseColorに足して輪郭を光らせる
float f = fresnel(geom, 2);
mat.baseColor.rgb *= 1 + f * uLowValue * 10;

// 眼だけ光らせる
mat.baseColor.rgb += geom.eye * uHighValue * 10;

輪郭は低域、目は高域に反応して光る、という実装をします。
これで低高域に反応した時に光りながら、中域でギュムギュムと動く頭の塊になります。

ezgif.com-gif-maker (4).gif

頂点数多めで全部違う形で違うタイミング、とかになるとVATだと無理なので、
こういうアプローチで作ります。
リアルタイムでどう実装できるかを常に考える
というのが重要だと思います。

ちなみにfbx向けにアトリビュートをいじる必要がありますが、
UEでもUnityでも全く同じ考え方で動かすことが可能なので、
シェーダー芸ベースで考えることで、ソフトウェアを覚えなおす苦痛から少し解放されます。

終わり

ほとんどHoudiniの記事になってしまいました。
あと、フクロウの書き方みたいな手順すっ飛ばし系の記事でもありますが、
何かの参考になったら幸いです。

追記

頭の煮凝りを作るときに、23フレ目と24フレ目を抜いてると書いてましたが、
自分で貼ったgifを見直したら、フレームを止めるノードが1個だけで、え??となり

シミュレーションをかけたローポリメッシュでハイポリを動かすノードのパラメータをいじる。
フレームは同じで、ギュムギュム感を変えたものを2つ用意する

つまりPoint Deformのパラメータを変えたものを2つ作る

でした。

やってることあまり変わらず、話がわかりにくいのでそのままにします。

30
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?