nPassとMesh Rendererでメッシュをばらまいてみる

InstaMATは後発とはいえ、かなりいろいろな機能があって可能性を感じるアプリです。
今回はその中でも面白そうなnPass ElementとMesh Rendererを使った簡単なテストを行ってみます。

まず、新しいプロジェクトとしてnPass Element Graphを選択します。

テンプレートとしてScatterサンプルがありますが、今回はこちらを参考にしています。
ただ、作成するプロジェクトはテンプレートを選択しないようにしました。

作成したグラフにはこの2つのノードが最初から存在します。
nPass Element Graphはグラフを指定回数ループすることが可能なグラフで、この2つのノードはループ処理の初期化部分とループ結果の出力部分です。

[On Execute Assignment]はループの初期化部分で、nPass変数というパラメータ群を初期化することができるノードです。
nPass変数はグラフのループ内で使用される、いわゆるローカル変数です。
もちろんパラメータペインで編集もできますが、入力パラメータを利用して初期化することもできます。

[Did Execute Assignment]はループ処理の結果を出力し、次のループへ情報を渡すノードです。
[Pass Index]については自動的に加算されるようなので、コネクタは存在しますが特に何もしなくてもOKです。

次にグラフのパラメータペインで入力パラメータとして[Mesh]を、nPass変数として[Buffer]を追加します。
[Mesh]はElementMeshを選択、[Buffer]はElementImageGrayを選択します。
[Mesh]の初期値はデフォルトアセットにあるBevel Cube.fbxを設定しておきます。

また、今回はメッシュを描画する関係でパフォーマンスが厳しい場面も出てきます。
そのため、ループ回数はあまり大きくしないほうがいいでしょう。
nPass Element Graphのデフォルトループ回数は1ですが、最大値が1024となっていますので、32くらいまで最大値を下げておいたほうがいいです。
パラメータペインのλのボタン(緑枠)を押すと選択中のパラメータの詳細を設定できるようになります。
[Pass Count]パラメータを選択してからボタンを押し、最大値として32を設定しておきましょう。

では、メッシュをレンダリングしてみましょう。
入力パラメータの[Mesh]をグラフ内にD&Dし、これを[Mesh Render]ノードを追加して接続してみます。

すると、このようにメッシュが描画されます。
[Output]コネクタにはライティング結果が提供され、ベースカラーやマスク情報なども取得できます。
今回はテストなので高さ情報のみを取得します。

とりあえず[Mesh Render]ノードのパラメータを操作して回転やスケールなどを試してみてください。
何故かメッシュの回転は存在しないのですが、カメラの回転があるのでこちらで回転は対応できます。
また、今回はばらまいてテクスチャとして利用することを想定していますので、[Camera Type]パラメータを[Orthograpic](Orthographicのtypo?)に設定しておきます。

さて、メッシュをばらまくとして、ばらまいた複数のメッシュがすべて同じ回転だったらおかしいですよね。
ですので[Camera Orientation]パラメータを変更したいのですが、これをループごとに変更したいと思います。

まずnPass変数から[Pass Index]をD&Dしてグラフに追加します。
次に[Random Number Vec3]ノードを検索して追加します。
このノードの最小値を0.0、最大値を360.0にし、[Seed]コネクタに[Pass Index]を接続します。

これで360度以内の乱数値を得られるので、[Mesh Render]の[Camera Orientation]に接続します。
SDと違って、ノードの各種パラメータはコネクタで簡単に接続できます。
初期状態ではコネクタは表示されていないのですが、入力コネクタの[拡大する]ボタンを押すとすべてのコネクタが表示されますので、接続してください。
ただし、拡大したままだとかなりノードが長くなって邪魔ですので、必要なコネクタに接続した段階で[閉じる]ボタンで縮小しましょう。

次に[Wrap Transform]ノードに[Mesh Render]の[Depth]を接続します。
このノードは回転・拡縮・平行移動を行うノードで、Wrapとあるように上下左右でラップします。
ここで平行移動と拡縮を行います。
回転と同様に、ランダム値を生成します。拡縮はユニフォームスケールとしますので、乱数を1つだけ生成してVec2に拡張します。

さて、これだけでは1つのメッシュしか表示されませんので、ループを利用してメッシュを増やしていきます。
まず、[Blend]ノードを利用して[Wrap Transform]の結果と[Buffer]をブレンドします。[Buffer]はパラメータペインからD&Dします。
ブレンド方法で最大値を設定すると、[Buffer]の内容と[Wrap Transform]の結果の最大値が選択されるわけです。
しかし、[Buffer]には初期値しか入っていないので、このブレンド結果を[Did Execute Assignment]の[Buffer]コネクタに接続します。
これによって、次のループでの[Buffer]の値が今回の処理の結果として渡されるわけです。
次のループのそのまた次のループは、今回と次回のループの結果をブレンドしたものになるわけで、そのまた次はさらに…ということになります。 では、[Pass Count]パラメータを適当に増やしてみましょう。

見ての通り、描画されたメッシュの[Pass Count]の分だけ配置されていることがわかります。
最後に出力パラメータを追加し、[Blend]の結果を接続すれば、ループの最後の結果を出力として利用することができるようになります。
最終的なグラフは以下のようになります。

このグラフを別のグラフから呼び出し、高さ情報からノーマルでも出力してみましょう。

コリジョンを取っているわけではないのでめり込みは発生していますが、想定されているメッシュばらまきからの高さ出力、ノーマル計算までできました。
コインを敷き詰めた床、ドクロの山のようなマテリアルはSDでも作っている方がいましたが、かなり高度なテクニックが必要になります。
この手法であればメッシュさえあれば簡単にできますし、メッシュのベースカラーなども設定すれば各種情報も得られるでしょう。
SDではこのようなことはできず、やるのであればHoudiniとか使うところではあるのですが、Houdiniを使うにはこのくらいだと少し大掛かりのようにも感じます。
その点でInstaMATは非常に扱いやすいツールだと思います。