非連続なジオメトリに連続的なマスクを設定する
SandBox:シェーダーなどで木を揺らすためのマスクを作成したい場合どうすればよいかを考えたもの

だいぶニッチな用途です。
やりたいこと
既存の木アセットに対して風などの影響を与えるためのマスクを作成したい。
ゲーム用の木を利用しようとした場合、頂点カラーでシェーダーの風の影響を受けるような設定がされていることがほとんど。

だがこの数値はアセットごとに想定シェーダーも異なるため、特定のシェーダー前提で動かす必要が多い。
シェーダー最適化工程などを考えると
- シェーダー統合がしづらい
- 不要なデータを持つ可能性
といった障害となりうるため、生成済みの木に対してもコントロール可能な係数を振れる仕組みを考えたい。
やろうとしているのは「生成済みの木」に対して実行するのが肝で、ゲーム用の木は枝~小枝~葉が非連続なメッシュで構成されていることが多いのでこの状態に対して連続的なマスクを振っていく。

生成結果
特定の頂点カラーが割り振り済みの木の頂点カラーをいったん白で塗りつぶしてから形状に合わせたマスクを作成する

- 木の根本から葉先までのマスク
- 葉の付け根の枝か、それぞれの葉先までマスク
の二通りを作成した。


試しにノイズで移動させると以下のように動いてくれた。(ノイズが適当で四方八方に動いていますが)
葉、木それぞれ影響度を設定する想定。



ノイズは以下のように2種類のマスクに対してVATでオフセットを設定するもので上記のテスト画像を生成している。

DistanceAlongGeometryノード
Houdiniドキュメント | Distance from Geometry geometry node
https://www.sidefx.com/ja/docs/houdini/nodes/sop/distancefromgeometry.html
今回利用したノードで、始点グループを定義し判定対象のコンポーネントが始点グループからどの程度離れているかのサーフェス表面上の距離を取得することができる。

入力データ
入力に使用したのは上述のとおり頂点カラーを一度削除した既存の木メッシュ。本来はUnrealEngine向けSpeedTreeシェーダー用の頂点カラーが設定されている。

また、葉と木はMaterialが分かれているのでこれを基準にする。

木の影響度のセットアップ
木全体の、根元から葉先に掛けてのマスクを作成する。
mask始点の作成
木全体のmaskの始点としてpointを作成する。
clipで木の根元のみを取得してバウンディングボックスのbottom centerを基準にした(が、木の形状によっては根があったりすると不具合が起きそうなやり方なのでここは検討の余地ありだと思う)。これに「start」というグループ名を設定。

影響度計算用のジオメトリを作成
葉と木全体を含むメッシュからscatterでpointを作成し、startポイントとmerge。

Connect Adjacent Piecesノードを点群に接続し、離散した点をつなぐカーブを作成

DistanceAlongGeometryを接続して、各点のstartからのサーフェース上の距離を取得する。

不具合回避としてdeleteでdistanceが-1になっている途切れたpointは削除(実装段階ではもう少し丁寧な不具合回避したほうが良いかと思います)。
attrib remapで正規化し、attribTransferで元のメッシュアトリビュートを転送。 分離したメッシュを含む、始点からサーフェース上の距離ベースのmaskができた。

葉の影響度のセットアップ
葉だけを動かすための、枝から葉先までのマスクを作成する。
元メッシュのpointから隣接カーブを作成
葉はquad polygonの集合体になっているのでscatterで計算すると葉ごとの影響度が乱数によるばらつきが大きそうなので元メッシュからConnect Adjacent Piecesでカーブを作成。こちらは始点はmergeせずにカーブを作成する。
(木のポリゴンだとポリゴン数が密度に対して差が大きそうなのでscatterしていました。似たような用途があった場合は物によって適切な隣接接続をすることになると思います)

Distance Along Geometryで頂点それぞれに対してbranchグループからの距離を計算する。
Distance Along Geometryは特定の1点だけではなくグループ化した複数のジオメトリからの距離を計算できる。

splitで枝グループのpointを削除(deleteは枝同様不具合pointの削除)

AttribTransferで葉グループに転送すると枝から各葉pointへの距離マスクが作成できた。

ニッチ用途ですが…。
精度周りはまだ調整したいものの、非連続なメッシュに連続した影響度を割り振る機会はたまにあるので、個人的にはこの「Connect Adjacent Piecesで接続したジオメトリで距離を計算し、元ジオメトリにマスクの転送」は結構色々使えそうなテクニックかなと思っています。

fish_ball
プロシージャル魚類