VFXGraphのSampleDataを見ていく:Orient編
はじめに
公式の解説動画(https://youtu.be/DKVdg8DsIVY?si=gtGdQXlly9FBJB2O)
Orient Face Camera
このエフェクトの肝は表題の通りOrientFaceCamera
なんだと思うんですが、それ以外の技術が気になりすぎてしょうがないエフェクト。
共通して使うパラメーターはpropertyで管理する
ここではTransformプロパティ
を用意して、オブジェクトの発生位置として随所で使いまわしている
VFXGraphでは1つのグラフの中で複数のエフェクトを管理していくのでこれをやるやらないでだいぶ効率も複雑さも変わってくる
Eyes Face Camera-Initialize Particle
SampleMesh
「任意のメッシュ(ここではEYE_Monster)を入力すると、その 三角形の位置 / 法線 / UV / 色 / インデックス などを取れるノード」とNoteに書いてある
ここではEYE_MONSTERというモデルにSubMeshが適用されている
Element0にあたるEyesが優先的に選択される(はず)
SingleBurstが100なので、SubMesh0のそれぞれのTriangle100個に目玉の発生位置として設定される仕組み
SubMeshとは
モデルに適用されているマテリアルごとに自動的に分けられる
Modeについて
-
Wrap
三角形数で 割った余り に変換して使う。
例えばメッシュに三角形が 100 個あって、Triangle = 105 のとき → 105 % 100 = 5 になる。
つまりインデックスがループする感じ。
→粒子数が三角形数より多いとき に便利。 -
Clamp
範囲外になったら 最後の三角形を使う。
例えば Triangle = 150 でも、メッシュに三角形が 100 個しかなければ、Triangle = 99 に固定される。
→外れ値を許容したくないときに安全。 -
Mirror
範囲外になったら インデックスを折り返す。
例えば三角形数が 100 の場合
Triangle = 101 → 98
Triangle = 102 → 97
つまり「行って帰ってくる」感じで反射する。
→ループより自然な周期性が欲しいときに使える。
SurfaceCoordinatesについて
-
Uniform
三角形の面積に比例してランダムサンプリングする。
大きい三角形ほど選ばれる確率が高くなるので、結果として メッシュ全体で均一な分布になる。
→「粒子を表面全体にバラ撒きたい」ときに使う。 -
Barycentric
各三角形の内部を barycentric 座標でサンプリングする。
つまり「三角形が選ばれたあと、その中で均等に配置される」。
ただし、この場合 大きい三角形も小さい三角形も同じ確率で選ばれる から、メッシュ全体だと大きい面がスカスカ、小さい面が密集しやすくなる。
→「各三角形に同じ確率で粒子を置きたい」場合に便利。
TexCoord.x(UV.x) → Size 入力へ
EYE_MONSTERのUVに埋め込んでおいた値を粒子のサイズとして利用している
EYE_MONSTERの三角形のUVSet2を確認すると、U座標にそれぞれ数値が入っていることが分かる
![]() |
![]() |
---|---|
0.35くらい | 0.18くらい |
Eyes Face Camera-Update Particle
なんでRotate 3D
の値をSetPosition
に?となったが、
目玉はずっとこっちを向く球なので、位置だけを動かしてるんですね
これはOrientFaceCamera
らしいところかもしれない
Eyes Face Camera-Output Particle
ここでも注目するのはOrientではなく、ノイズの作り方
Noise1D
のCoordinate
に値を流すとノイズが生成される仕組みだが、
・TotalVFXTime
で毎フレーム変化を付ける
・RandomFloat
でパーティクルごとにズレを作る
このようなノイズ生成は今後も頻繁に使用するシステム
RandomFloat
ノードの設定に注意で、SeedがPerParticle
なのでパーティクルごとに設定され、Constantにチェックが付くことで最初の一回だけ生成される。
NoiseのRange
は0~1にしておいて、各項目用に後ろでLerp
する時の補完係数として利用している
Body-UpdateParticle
このAxisX/Y/Zの取り決めが個人的に大変悩まされた部分
Rotate3Dノードの理解
このあたり、「ベクトルは座標である」という概念を以下の3Blue1BrownJapanさんの動画シリーズで学んでいたおかげでそこまで躓かずに進めた。
【入力】
Position … 回したいベクトル
Rotation … 軸
Angle … 回転の量。ラジアン値(πとか)
Rotation Center … 軸の中心位置、らしいが現状使い道が分からない
【出力】
Position … 回転後のベクトル
段階
1.回転させたい方向ベクトルの入力
2.回転軸の指定
3.角度を与える
4.出力ベクトルの利用
解説
1.サンプルで回転させたいのはYベクトル(0,1,0)
2.Xを軸(1,0,0)に回転させたい
ここでは-1。右手座標左手座標というやつに影響を受けている
3.なんで悩まされたかというと回転中、Z座標も変動することを失念していたこと
例えば45度回転したとき、(0,0.7,0.7)
Zベクトルを規定しないと「どこにいけばいいの?」とモデルが破綻する
なので、Zベクトルも規定してあげる必要がある
4.Zベクトルは回転軸であるXベクトルと、回転中のYベクトルの外積によって導き出せる
なのでスクショのようなノード構成となる
例:首を振りつづける場合
1.PositionでZ軸をセットし(0,0,1)
2.回転軸RotationAxisをY軸にセットする(0,1,0)
3.出力されるベクトルは回転中のZ軸なので、そのZ軸と固定されたY軸(0,-1,0)の外積を取ることで、
残り1つの軸であるX軸を求める。
4.VFXTimeをSineに繋ぎ、Angleにつなぐ
Orient Fixed Axis
Eyes Fixed Axis-Initialize Particle
いよいよ本格的にカスタムアトリビュートが使用されてくる感じ。
SampleMeshから出力されるPositionや法線方向、UVに格納されているスケールを保持しておく。
Eyes Fixed Axis-Update Particle
Look At
ある点から別の点を向かせるための方向ベクトルを作成する
Initializeで手に入れて置いたInitPos、InitDirectionをここで使う
入力名 | 内容 |
---|---|
From | どこから見るか |
To | どこを見るか |
Up | どこを「上」とするか |
Fromにはパーティクルの生成される座標(InitPos)、ToにはTransform(オブジェクトの中心)、Upには法線方向を繋げている。
中心への向きだけで安定しそうだが、法線方向を「上」と設定しなければ、自由にひっくり返る余地を与えてしまうことになる。
Transform(Matrix)
変換行列を作るノード。これもまさに線形代数のエッセンスのおかげで理解できた。
ここでは、
1.LookAt
で基準となる座標系を作成
2.Transform(matrix)
が事前に作られた変換行列に従ってその座標を変換する
個別に「回転」「移動」等を足すよりも、行列一回の掛け算の方が処理も楽らしい
LookAt
で粒子ごとの基準の姿勢を作り、
Transform(Matrix)
でモデルの表面に移動。
SetOpen
は100個単位(Modulo 5000%100)でバラバラに設定しているから
サンプルデータのような100個が順番に花開くような見た目を作れる
Open Animation
Update内で'Open'というFloat型のカスタムアトリビュートを作成し、
さらにこのアトリビュートのデータをいじって'PositionShapeCircle'のRadiusに使用することで、花が開く動きを付けている
これはすごい
Eyes Fixed Axis-Output Particle
Orient: Fixed Axis
Upを指定してあげるOrientノード
Normalを接続すれば、Normal方向に向いてくれる
それの応用版がこのノード構成
Note翻訳 AxisDirection
initial direction 属性は目のソケットから外に向かう法線で、Direction 属性は update context 内の Position arc circle block によって設定され、円の法線に対応する。orient block に軸を与えるため、initial direction と direction attribute の間を lerp(補間)しており、その補間には Flower Animation の open 属性を使用している。
Orient Advanced
Output Particle
Orient Advanced
サンプルではZYを指定する
Note翻訳 Orient Advanced
アドバンストモードでは、orient block は2つのベクトルを必要とする。Z軸は正面ベクトル、Y軸は整列ベクトルとなる。ここではパーティクルを常に球の法線方向に向けたいので、Z軸はパーティクル位置−球の中心で得られる法線とする。Y軸の整列ベクトルは速度ベクトルを使い、粒子が進行方向に揃うようにする。また、ベクトルを正規化する必要はなく、Orient Block が自動で正規化処理を行う。
私の感覚ではZって奥行じゃないの?とか座標系イメージがぐちゃぐちゃになってしまうんですが、
・Unity の Quad の表面法線は ローカル Z+
・ローカル Y は縦方向(アップベクトル)
この原理だけ覚えたらすっきりしました。
まとめ
Orientが主題なだけあって、かなり座標軸に振り回される内容だった。
おかげでふわふわしていたエフェクト作成時の座標の扱いが見直せた。素晴らしい。
Discussion