TouchDesigner Advent Calendar 2018 21日目の記事です。
はじめに
安定性に定評のあるTouchDesignerですが、沢山の3Dモデルを配置したり、一度に大量のオブジェクトを動かそうとするとFPSの低下が起きてしまいます。
リアルタイムレンダリング命のTouchDesignerが、カクカクしているとなんとも切ない気持ちになるのは避けられません。
そこで今回はGeometry instancingというテクニックと、**GLSL(シェーダー言語)**を使って大量のオブジェクトを描画しつつ、それらを滑らかに動かそうというのが目的です。
サンプルプロジェクト
こちらに今回のサンプルプロジェクトをアップしましたので参考にしてみてください。
GoSato/GeometryInstancing_GLSL (GitHub)
ゴール
こんな感じに、スッっと出てきてワサワサーと動くものを作ります。
gifだと画質とFPSに限界があるので、画質の良いものはvimeoに貼っておきます。
Geometry instancing x GLSL TouchDesigner (vimeo)
Geometry instancingとは
簡単に説明すると画面に大量にオブジェクトを描画したい時に、CPU側からの描画呼び出しは1回で同じメッシュのコピーを大量に描画するテクニックです。
これによりドローコールを大幅に抑えることができます。
ゲームではパーティクルや草、木など画面上に大量に必要なものに使われます。
Geometry instancingの準備
Geometry instancingを使うためには「大量に生成する元となるメッシュデータ」と「生成させる位置となる座標データ」の2つが必要になります。
この画像では「teapotオブジェクト」を「boxの頂点座標の位置」にinstancingしています。
これを「草」に変えて、生成位置を「平面上のランダムな位置」にすればフィールドに大量の草を生やすことができると言うわけです。
TouchDesingerでの使い方
3Dオブジェクトの描画準備
まず始めにGeometry OP
、Camera OP
、Light OP
とRender TOP
を配置し、3Dオブジェクト(torus)を描画します。
これは「大量生成する元となるメッシュデータ」になります。
ここまででTouchDesignerの基本である3Dオブジェクトの描画ができたと思います。
Geometry OPの設定
次にGeometry OP
を選択し、InstanceタブのInstancingをオンにします。
画面上に何も表示されなくなりますが、これは「生成する位置となる座標データ」を指定していないからです。
生成する位置となる座標データの用意
今回はShere SOP
を使用します。
頂点座標を取得するためにSOP to CHOP
にSphere SOP
を設定。
これで下準備終了です。
Geometry OPにSOP to CHOPで取得した値を反映
あとはGeometry TOP
のInstanceタブを画像のように設定。
Render TOP
上で描画結果を確認するとtorusが大きいために重なって表示されているので、大きさを適度なサイズに変更します。
完成
このようにGeometry instancingを使って「ドーナッツ(torus)」を「球面上の位置」に大量生成することができました。
動きをつける
これでは地味なので動きをつけてあげます。
Geometry Instancing Demo (vimeo)
Transformの値を変えることによって動きをつけています。
本題
ここまでは入門編みたいな感じで、ここからが本編です。
このようにGeometry instancingで生成した大量のオブジェクトをGLSLで動かしたいと思います。
GLSLとは
GLSLとはOpenGL Shading Languageの略称で、いわゆるシェーダー言語と呼ばれるものです。
GPUを使用した並列処理のため、高速に描画を行うことができるのが特徴です。
下準備
「大量に生成する元となるメッシュデータ」と「生成させる位置となる座標データ」の2つを用意します。
一番最初に載せたものでは四角形の平面に、タイル状に並べられた六角柱が上下にワサワサしていました。
「大量に生成する元となるメッシュデータ」が「六角柱」で、「生成させる位置となる座標データ」は「四角形の平面」になります。
そして、ワサワサの部分がGLSLで記述した動きです。
ハチの巣模様の平面を作る
これはGrid SOP
を使用しているのですが、そのまま使おうと思うと六角形が隙間なく並ばずに、頂点同士が当たってしまいます。
頂点同士がぶつからずに、六角形の形を生かしてハチの巣状に並べるには一工夫必要です。
今回説明は割愛しますが、簡単に説明するとSelect CHOP
を使用して各頂点のx座標を抜き出し、Script CHOP
を使って奇数行目のx座標を六角形の横幅分ずらしてあげることで前後の頂点がぶつかることなく並べることができます。
具体的にどういった処理を行っているかはScript CHOP
の中身を見てみてください。
六角柱の3Dモデル
こちらはTouchDesigner標準のSOPにはないのですが、サンプルプロジェクトのGeoフォルダの中に入れてあるのでそちらを使ってください。
Blenderなどを使えば複雑な操作なしに簡単に作れるので、欲しい3Dモデルがあれば自分で作ってしまうのも手です。
頂点を指定すればTouchDesigner上で同じものを作るのも可能です・・・若干面倒ですが・・・
今回はタイルのように使いたいのでx軸で90度回転して寝かせてあげます。
Let`s Geometory instancing
これで下準備が終わったので、あとは先ほどの説明の通りにGeometry instancingの設定をしてあげれば
「四角形の平面に、タイル状に並べられた六角柱」の完成です。
残すはシェーダーで動きをつけてあげるだけです。
GLSLで動きをつける
今回はPhongシェーダをベースに、主にVertexシェーダーをいじってあげることで波打つような動きにします。
Phong MAT
を選択し、OutputシェーダーボタンからPhongシェーダーベースのVertexシェーダーとPixelシェーダーを作成します。
こちらの左側が標準のPhongシェーダー、右側が今回用に実装したy軸縦方向にニュッと伸びる処理を描いたシェーダーです。
コメントアウト分があるのでわかりづらいですが、実際に書き換えているのはほんの数行程です。
Vertexシェーダー
やっていることを簡単に説明すると、Geometry instancingで生成したオブジェクトごと(六角柱1つ)にy軸正方向にスケールをかけて、縦に伸ばしてあげます。
newP.y *= max(0, TDPerlinNoise(TDDeform(vec3(0)).xyz + vec3(0, uTime, 0))) * 200;
この時、生成したオブジェクトごとにランダムな値でスケールをかけるのがポイントです。
TDPerlinNoise(TDDeform(vec3(0)).xyz
頂点ごとにスケールをかけるとそれはそれで違った動きをして面白いです。
Vertexシェーダー内でPatter A,B,C
という形でそれぞれ異なる処理が記述してあるのでコメントアウトを外してそれぞれの挙動を確認してみてください。
ぬるっとした動きはパーリンノイズがポイントです。
Pixelシェーダー
こちらはworld座標系のy軸の値に基づいて色を変化させています。
diffuseSum *= vec3(0.5, 0.0, iVert.worldSpacePos.y*4.5) * iVert.color.rgb * uDiffuseColor.rgb;
この辺は個人の好みの問題だったりするので良い感じに調整してみてください。
仕上げ
仕上げとしてSSAO TOP
やLevel TOP
、Ramp TOP
を使って色味を調整してあげれば完成です。
最後に
こんな感じでGLSLを使うことでパフォーマンスを維持しつつ、大量のオブジェクトに対して複雑な動きをつけてあげることが可能です。
TouchDesignerやProcessingを使って作った作品をtwitterにぱらぱらと挙げているのでよろしくお願いします。
go (twitter)
— 5O | go (@0505_lab) 2018年12月16日
What is Mixed Reality?
— 5O | go (@0505_lab) 2018年12月13日
Made with STYLY#MR #STYLY pic.twitter.com/P7YWCXzakT
「Color Of The Year 2019」の「Living Coral」が個人的に超好きなカラーリングだったのでシェーダーで一発#COY2019 #GLSL pic.twitter.com/kZiC0iqj7j
— 5O | go (@0505_lab) 2018年12月8日
グラフィックからパターンを見出して数式に落とし込み、それを自分なりに味付けしてグラフィックに落とし込む作業 pic.twitter.com/UJWNAtp3IL
— 5O | go (@0505_lab) 2018年12月5日
#glsl pic.twitter.com/UqbsVUu53O
— 5O | go (@0505_lab) 2018年12月2日