うにty生活

UnityChanを生活させたい

Visual Effect Graphのサンプルを徹底解説 第一弾 - Portal

f:id:tubakihimeLoveHate:20200927175818p:plain

 

どうも、ラブヘイトです。

ここ最近Unity Visual Effect Graph(以下 VFX)にハマっておりまして、様々な動画をみています。

学習のためにも実際にサンプルの中身覗いてみるか!と思い開いた訳ですが......

f:id:tubakihimeLoveHate:20200927180109p:plain


見る気がなくなるノード構成、意味わかりません。見るだけでなく、1からサンプルと同じようにも作ってもみました。

 

もちろん同じように動きましたが、どうしてそうなっているのか、何を意図してそのノード構成になったのか全くわからないので、今回はサンプルVFXについて徹底解剖して行こうかなと思います。最初はPortal!

 

知らないことが多いので、長くなること間違いなし!

 

f:id:tubakihimeLoveHate:20200927181645g:plain
サンプルは以下からダウンロードやクローンできます。

https://github.com/Unity-Technologies/VisualEffectGraph-Samples

 

一応グループ分けされているので、ノードグループごとにどんな役割でどういう計算をしているか、解説していきます。

※リファレンスが存在しない部分は自分が実際に動かしみて、機能を推測している部分もあります。

 

 

環境

Unity 2019.3.3f1

HDRP 7.3.1

Visual Effect Graph 7.3.1

 

Wobby Outline

f:id:tubakihimeLoveHate:20200927185127p:plain

このグループの出力は最終的に、Initialize Particle>Add Position from Map>Sample Positionに繋がります

f:id:tubakihimeLoveHate:20200927185157p:plain
 

Add Position from Map

Wobbly Outlineを説明する前に、最終接続先である曲者Add Position from Mapについて説明します。

まずこちらノードは検索で出てきません。Set Position from Mapを作成し、InspectorのCompositionをAddに変更することでノード名が変化します。

 

Add Position NodeはSetしたPositionに位置情報を加算します。

Add Positionを行うと何も設定していなくても、Torusから外れた位置に加算されてしまいます。

f:id:tubakihimeLoveHate:20200927183638p:plain

 

Value Biasを「-0.5」に統一するとSetしたPositionの位置に表示されるので、

Add Posisionで必ず初手に行う設定になります。(わかるか!)

 

そして本題のWobbly Outlineグループが最終的に何をしたいかと言うと、アニメーションした先の、円のアウトラインを歪める表現を行っています。

f:id:tubakihimeLoveHate:20200927184159p:plain

※わかりやすく別の効果は切ってあります。

 

Wobbly Outline(計算)

それではやっとWobbly Outlineの中身についてです。上下に分けて説明します。

上2つのノードはパーティクルのPositionと0.34をMultply。0.34はアウトラインの歪み具合なので、この値を増減させることで歪み幅を調節できます。

 

動的に値が変化するノードはTotal time。これによってアニメーションが実現可能です。

Total Timeはパーティクルごとのデルタタイムで変化していくノード。

Vector3[0,-1,0]の部分で、y軸のみ変化させるように設定しています。

 

つまりこのグループノードが示していることは、現在のPositionとTotal timeを掛け合わせ、Add Position>Sample Positionに接続すると揺れるアニメーションができると言うことです。調節で多くのノードを配置しているだけで、ほぼ同じ表現をするのに最低限必要なノードはこれだけです。

f:id:tubakihimeLoveHate:20200927185512p:plain

音ゲーのエフェクトとかに使えそうですね

 

Source Torus

f:id:tubakihimeLoveHate:20200927185837p:plain

Initialize Particle>Arc Torusに遠くから接続されているSource Torusというノードが存在します。これは正しくは、Arc Torusノードで、Sorce Torusと名前を付けたプロパティです。

Torusの半径や位置を簡単にInspectorから編集するためにこのような接続方法になっています。

 

Compose Initial Brighness(into Color)

f:id:tubakihimeLoveHate:20200927190049p:plain

これはNodeグループというかただのCurveですが、気になるのはグループのタイトル

初期輝度という意味なので、つまりHDR。

接続先がSet Colorなので、やっていることはわかりますが、その接続方法だけでHDRだけを制御できるの?って話です。

 

試しにSet ColorにfloatとVector3で入力型を変更してみました。

f:id:tubakihimeLoveHate:20200927190445p:plain

f:id:tubakihimeLoveHate:20200927190502p:plain


入力がfloatなら、輝度のみ。Vector3なら色を制御できるみたいです。

これはなんとなく予想できたけど、やっぱり入力型で役割違うのか!奥が深い!

 

 

Compose Velocity(ベクトルの大きさ)

f:id:tubakihimeLoveHate:20200927201519p:plain

このノードグループは様々なノード出力の接続先になっていて一見複雑そうに見えますが、

多分計算ノードが多いからそう見えるだけだなと思います。

Velocityの要素は2つに分けることができて、方向と大きさに分けることができます。この2つを分けて説明していきます。

 

まずはベクトルの大きさを決めているノードから

Random Numberはその名の通り指定した最小最大の中でランダムな値を出力します。

サンプルでは0.8から2.0の間で速さをランダムで出力しているので、大きく飛び散るもの、小さく飛び散るものがあっていい感じです。

 

以下Random Number[0.8,2.0](左)と[2.0,2.0](右)で比較した時の画像です。

エフェクトはランダム性があるほどいいですよね。

f:id:tubakihimeLoveHate:20200927202433p:plain


次、Sample Curve>Timeに他のグループから接続されているので、Timeの値によってベクトルの大きさが変化していきます。

ここで一旦Compose Velocityの他の要素は置いといて、Sample Curve>Timeへの接続元である、Pulse rotation Maskグループから解明していこうと思います。

 

Pulse rotation Mask

f:id:tubakihimeLoveHate:20200927203000p:plain

 

Rectangular to Polar

Rectangular to Polarノードはxとyから極座標を求めます。

極座標とはr(動径)とシータ(θ)で点の位置を表す座標です。サンプルでは最終的にシータのみ扱ってます。Angle on TorusグループではTimeとSpeedを掛け合わせてるだけなので、

Remapノードまでを式に表すとこんな感じでしょうか(多分あってると思います)

{(Time * Speed+xθ) % 2π}/2π

Moduloノードは余りを出力するのですが、正直計算式をみても意図が読み取れませんでしたが、θが変化した時の値を追っていくと

 

θ° (θ%2π)/2π
69 0.98
70 0.14
71 0.3
72 0.459
73 0.618
74 0.777
75 0.936
76 0.095
77 0.254
78 0.414
79 0.573
80 0.732
81 0.891
82 0.057

 

グラフにしたら以下のようになります。

f:id:tubakihimeLoveHate:20200925033733p:plain

このグラフとパルスというグループ名から、円周用パルス信号だと推測しました。

3°ごとにVelocityの大きさが最大になるということがわかります。

 

ただ、Shader GraphみたいにWaveノードがあればこんなに複雑にならないのでは?と思いましたが、VFXの方には実装されていないみたいです。

 

Particle-To-Center Vector(World)

f:id:tubakihimeLoveHate:20200927234138p:plain

このグループでは円の中心とパーティクル座標の差をオフセットとして取得しています。

出力はRectangular to Polarノードに接続されています。

これで、velocityのベクトルの大きさを決定するノード解説は終わりました。

次はベクトルの向きです。

 

Compose Velocity(ベクトル向き)

f:id:tubakihimeLoveHate:20200927234646p:plain

またCompose Velocityに戻って、力の加わる向きについて追っていこうと思います。

ノード内でいうと黄色の接続がVectorなので黄色線を追うとわかりやすいです。

このグループノードではAddしているだけなので、一旦置いときます。

 

一旦Vectorノードに置き換えている理由は、グループにした時にわかりやすくするためだと思います。

 

Expel Particles on Z Axis based on Wobbly offset

f:id:tubakihimeLoveHate:20200927234925p:plain

このグループはパーティクルのローカルZ軸に力を加えます。横からPortalを見て、接続を外してみるとわかります。

f:id:tubakihimeLoveHate:20200927235242p:plain

ただ、Change Spaceノードでワールドからローカルに変更している意図はわかりませんでした。あってもなくても変化は見られない......。グループ名もよくわかりません。

ここではChange SpaceノードでWorld to Localが出来ることを覚えていればいいでしょう。

 

Get Torus Tangent

円の接線を取得するノードグループです。

Cross Product

2つのベクトルのベクトル積を計算します。私も詳しいことは知りません。さっき調べました。

Cross ProductからNormalizeノードでなぜ円の接線が取得できるのか、わかりやすく円周上の4つのポイントで考えていきます。

 

前提は以下です

Torusの中心:(0, 1.07, 0)

TorusのMajor Radius:1

f:id:tubakihimeLoveHate:20200928014254p:plain


このようにどの位置にいてもベクトルが円の接線上にあることがわかります。これ再現できる人すごいな.......

方向を逆にするにはCross Productを(0, 0, -1)にすればいいと思います。

 

Random Numberはベクトルの大きさを調節できます。Compose VelocityグループのRandom Numberとの違いはよくわからなかったです。

 

この接線上のベクトルは次のRandomize tangentグループに渡されます。

 

 

Randomize tangent

f:id:tubakihimeLoveHate:20200928004222p:plain

このノードグループで、先ほど求めた接線上のベクトル方向をランダムに傾けています。

 

Rotate 3D

Position:velocityを入れます

Rotation Center:TorusのCenter

Rotation Axis:回転させる軸です。(サンプルではZ軸回転)

Angle :Rotateさせる量

傾け方もランダムになっています。 

 

ここまできてようやくVelocityが終わりました、あと少しです。

 

Categorize Particles/Height Mask

f:id:tubakihimeLoveHate:20200928004501p:plain

f:id:tubakihimeLoveHate:20200928004521p:plain 

ここで行っていることはHeight Mask(高さの閾値)を設定して、一定以上の高さでパーティクルの生存時間を分岐させています。一定以上と言っているもののRandom Number多用してて閾値の実態が掴めないところがなんともわかりづらいです。

 

Noise Intensity over Life and elevation

f:id:tubakihimeLoveHate:20200928004657p:plain

Lifetimeの後半で大きく力が加わるようになっています。ここでもHeight Maskから値を取得しています。

 

Cancel Gravity

f:id:tubakihimeLoveHate:20200928004824p:plain

Gravityを切っていたので忘れていました。このグループでは、particleのY軸が0.02より大きい時は重力を与え、そうでない時は0にしています。ポータルの下部は重力の影響を受けていません。

 

その他ノード

あとはコンテキスト内のなんだこれって思ったノードを調べます。

 

Set Mass Random

f:id:tubakihimeLoveHate:20200928005756p:plain

リファレンスには載ってなかったです。MassはRigidbodyで出てくる質量のことなので、パーティクル一つ一つの質量をランダムにしているという推測です。

 

Linear Drag

f:id:tubakihimeLoveHate:20200928005821p:plain

オブジェクトの移動による物理計算を考慮するかどうかです。普通のパーティクルでもそんな設定項目があった気がします。

比較も作成したのですが、VFXはgifで載せるとわかりづらいのでやめときます。

 

Orient Along Velocity

f:id:tubakihimeLoveHate:20200928010157p:plain

意外と大切なノードで、Velocityの方向にParticleを引き伸ばしてレンダリングします。

このノードがないと結構ダサいことになります。

f:id:tubakihimeLoveHate:20200928010323p:plain

 

まとめ

色々調べた結果、ノードリファレンスはVisual effect graph 7.0以降更新させてないみたいです。なのでそれ以降に追加されたノードは公式の説明がない状態でわからないことも多いです。

 

学べることは多かったですが、文量も多いので第2弾やるかは微妙なところ

早く自分で色々作れるようになりたいぜ!

 

一番最初に添付した画像ですが、ポータルの中身をShader Graphと組み合わせて歪ませてみました。あとはポータルの中に違う風景を映し込めたら最高ですね!

f:id:tubakihimeLoveHate:20200927175818p:plain

 

HDRPで歪ませるShader Graphを作成する方法はこちら

【Shader Graphに入門してみた】HDRPで歪み表現 3日目 - うにty生活

 

今回最長です。5500文字、頑張った。

それではまた