Instance Noodlesとは
DirectX11のCompute Shaderを使ったGPGPU計算や、Geometry Shaderを使ったジオメトリ制御を、普通のVVVVのノード感覚で扱うためのContributions(ライブラリ)です。
VVVVにデフォルトで含まれているMapやGamma、Vectorなどの基本的なノードのCompute Shader版が大量に含まれているので、自分でシェーダを書かなくても手軽にGPGPUが使えます。
下に貼ったのは300000個のパーティクルをCurlノイズをかけてうねうねさせてみた感じのパッチと、その描画結果です。こんな感じで比較的シンプルなパッチで手軽にGPGPUできます。
下記のパッチで言うとBrownian
, Curl
, Vector3DSplit
, Map
, Vector3DJoin
, Polar
, SpriteBuffered
はすべてInstance Noodlesに含まれるノードで、中身はシェーダを呼び出すだけのパッチになっています。
インストール
前提として、DirectX11を使ってるのでDX11 packsが必要になります。
入れてない人は vvvvのインストールガイド[DX11対応] - Qiita を読んでDX11 packsの導入を済ませておいてください。
Contributionsページのdownloadからzipファイルをダウンロードし、解凍したフォルダをVVVVのインストールフォルダ内のpacksフォルダに置くと使えます。
...\packs\InstanceNoodles\girlpower\Compute\01_ComputeBasic.v4p
を開いてうまく動いていれば導入は完了です。
導入後はgirlpowerと ...\packs\InstanceNoodles\nodes\modules
フォルダ内を見て、どんなパッチが用意されてるのかと、ヘルプパッチで扱い方をひと通り確認しておくと良いです。
パーティクルを出してみる
まずは簡単なところから。
上のパッチでも使っているBrownian
というノードを使ってみます。これはブラウン運動をシミュレーションするノードで、指定した数分のブラウン運動する座標値が取得できます。
Brownian
の出力はSpriteBuffered
のPosition 3D Buffer
につなぎます。SpriteBuffered
はパーティクルを表示するためのシェーダだと思えば良いです。
Brownian
とSpriteBuffered
のSpread Countインレットにはそれぞれ描画したいパーティクル数を設定します。
SpriteBuffered
の出力はDX11 Layerなので、あとはこれをDX11用のRendererに繋げばパーティクルが表示されます。
表示できたらパーティクル数をどんどん増やしてみてください。
座標値をGPU側に転送してGPGPUで計算しているので、かなりパーティクル数を増やしてもあまり処理落ちしないはずです。
手元のGeforce 940Mだとパーティクル1000000個出しても48fpsぐらいは出る感じです。
CPU-GPU間の値の受け渡しについて
GPUで計算する場合、計算に必要な値は基本的にGPUのStructured Bufferに転送しておく必要があります。CPU→GPUへの転送はDynamicBuffer
というノードを使用します。
例えば、RandomSpread
で生成した100000 * xyzの値をInstance NoodlesのAttractor
で使用したい場合、そのままSpreadを渡すことはできないので、DynamicBuffer
でGPUに転送したうえで渡すような使い方になります。
また、計算結果に関してもGPUに保存されているため、Spreadとして取り出す必要がある場合はGPU→CPUへの読み出しを行う必要があります。これにはReadBack
というノードを使用します。
まとめ
だいたい基本的なところはこんな感じかな……?パッチはGitHubに置いておきました。
vvvv-sandbox/InstanceNoodlesSample at master · clomie/vvvv-sandbox
今回は触れなかったけど、他にもDX11.GeomFX系のGeometryにエフェクトかけられる感じのノードとかあって、そっちはそっちでめちゃめちゃ便利そうなやつが大量にあります。
現状でもBufferを扱えるノードはだいぶ充実しているので、たぶんInstance Noodlesを導入するだけでもかなりいろいろできるはずです。Damperがないのがちょっと痛いぐらい。
VVVVでDX11やるならpacksと一緒にとりあえずで入れておいていいぐらいだと思います。
DX9でGPGPUしたい場合
Vertex ShaderとPixel Shaderでテクスチャの各ピクセルの色情報をただのfloat値として扱って計算することになるっぽいです。
DirectX9でもGPGPUしたいという人は以下の記事が参考になります。