はじめに
本記事ではBlenderのパーティクルシステム、ダイナミックペイント、ジオメトリノードを連携する方法について色々検証したので振り返り用にまとめてみました。
同じ様に悩んでいる人の助けになれば幸いです。
目次
モチベーション
ことの発端はBlenderでアニメの1シーンのようなリッチな雨の風景をつくりたい!という感じです。(新海誠監督の「言の葉の庭」の雨のシーンみたいな・・・)
Everything CGさんの作品(https://www.youtube.com/watch?v=TP2wG8yFlAw&list=PLsuDLbyvLYgq3vxV3afbdCUHWJKZ6_IXz&index=5) のHoudiniファイルで考え方を学んでBlenderで再現してみました!
まず、雨のシーンの構成要素として今回は雨粒、リアルな水面の波紋、雨粒が水面に落ちたことで発生する水飛沫を制作しました。雨粒をパーティクルシステム、波紋をダイナミックペイント、水飛沫となるセルルックオブジェクトのアニメーションをジオメトリノードでそれぞれ制作しました。ここで雨のシーンは
雨粒が水面に落ちる → 波紋が発生する → セルルックの水飛沫が発生する
の順でアニメーションが動きます。
よってこの3つの動きをスムーズにアニメーションさせるにはパーティクルシステム、ダイナミックペイント、ジオメトリノードの3つの連携が必須になります。
パーティクルシステムとダイナミックペイントの連携は既に他の方のたくさんのチュートリアルがあるのでそちらをご覧ください。
問題はダイナミックペイントとジオメトリノードの連携もしくはパーティクルシステムとジオメトリノードの連携です。自分が調べた範囲ではほとんど記事がなく1か月くらい悩んだので今回記事にすることにしました。
このプロジェクトでは
①ダイナミックペイントと既存のジオメトリノードで組み合わせた手法
②パーティクルシステムと自作アドオンParticle Trackerを用いた手法
③パーティークル含めすべてジオメトリノードで作成する手法
の3つの手法について検討しました。
一つずつ記事にしていく予定です。今回は①の手法を解説します。
目標
雨粒(パーティクル)が落ちた位置で水面を揺らして更に水飛沫オブジェクトを配置する
解説
まず今回つくったダイナミックペイントとジオメトリノードについて軽く解説します。
まずダイナミックペイント
このようにパーティクルシステムシステムをブラシとしてキャンバスであるグリッド(水面)を動かします。
後述しますが今回の手法ではグリッドの分割数も重要なパラメータとなってきます。
今回はキーフレームを使わずシミュレーションゾーンを使って2コマ打ちでアニメーションを動かしています。
また水飛沫オブジェクトのアニメーションは「ポイントにインスタンス作成」ノードを使っています。
水飛沫は基本的にモディファイアとジオメトリノードでプロシージャルに作成しました。
次にどのようにダイナミックペイントとジオメトリノードを連携させたかの考え方を説明します。
まずワークフローと図は下記のようになります。
ポイントは
・水を揺らすダイナミックペイント「波」と重みを表すダイナミックペイント「ウェイト」を使うこと
・ジオメトリノードで頂点グループの重みを使った頂点のマージを行う
の2つです。
それぞれ解説します。
2種類のダイナミックペイント
まずダイナミックペイントのサーフェスタイプには複数の種類があります。最もポピュラーなのは今回も使ったリアルな水の動きを再現できる「波」です。波紋の動きについてはこの「波」を使いました。
今回はサーフェスタイプ「ウェイト」も使いました。「ウェイト」は頂点ウェイトグループを生成します。
頂点ウェイトグループとは重み付き頂点グループです。
重みをもっているのでパーティクルが当たった部分の頂点の重みは大きく、そこから離れている頂点の重みは小さくなります。
よって
「出力」の頂点グループの情報(上の図のdp_weight)を「名前付き属性」ノードでジオメトリノードに渡すことでパーティクルが落ちたおおよその位置の情報をジオメトリノード内で扱えるようになります。
ここでおおよその位置という表現をしたのは水面が複数の頂点からなるグリッドであることが関係しています。ジオメトリノードに渡しているのはあくまで重みを持っているグリッドの頂点グループでありパーティクルが落ちた一点の座標を渡しているわけではありません!
つまり複数のポイント(頂点)を渡しているので、このまま「ポイントにインスタンス作成」ノードにポイントを渡すと付近の複数のポイントで水飛沫オブジェクトが発生してしまいます。
この問題を解決するのが「距離でマージ」ノードです。
重みによるマージ
上の図は頂点の重みを円柱の高さで表したのもです。重みがパーティクルを中心に円状に広がっているのが分かります。
名前付き属性で「ウェイト」の頂点グループ情報を持ってきます(図のdp_weight)これを「距離でマージ」ノードの選択に繋ぐと重みに基づくマージができます。 重みのない点はマージされません(便利!)。
複数の点が一点にマージされたのが分かります。
重み付き頂点グループと「ジオメトリ削除」を組み合させてこのマージされたポイント以外を削除できます。
あとはこのマージされたポイントを使って水飛沫オブジェクトを配置してシミュレーションゾーンでアニメーションを動かします。
まとめと考察
以上よりダイナミックペイントとジオメトリノードの連携ができました。
しかしこの手法にも下記のような問題点があります。
・「距離でマージ」ノードのパラメータの調整が必須
・グリッド(水面)の分割数問題
前者について、距離でマージしているのですが確実に一点にマージされるのではなく場合によっては2点にマージされる場合があります。その場合は「距離でマージ」ノードを2つ使うと1つのポイントにマージされます。また、いい感じにマージするにはマージに使う距離の調整も必須です。
後者について、グリッドの頂点が頂点グループになるのでこの頂点の分割数が「距離でマージ」ノードのパラメータが影響してきます。分割数が多すぎるとマージしても複数の点になる可能性があり。逆に少なすぎるとそもそも「波」の動きが悪くなりまた、パーティクルがグリッドの間をすり抜けて頂点が重みを持たない場合がありました。
数カット程度つくる場合はパラメータの調整ができますが、もっと汎用性が必要な場合は改良が必要です。
次回は自作アドオン「Particle Tracker」を使った手法を解説します。
読んでいただきありがとうございます。
少し話は逸れますが雨粒のオブジェクト、雨のアニメーションの考え方は下記の動画解説を参考にしています。
とても参考になりますので雨のシーンについて知りたい人はぜひご覧ください。
雨のシーンの参考動画
-Everything CG さん
https://youtu.be/TP2wG8yFlAw?list=PLsuDLbyvLYgq3vxV3afbdCUHWJKZ6_IXz
-Tawan Sunflower さん