Skip to content
第14回 メッシュ表面からのパーティクル生成

2 / 4 VFX Graphで毛を表現する ​

このステップの目的

Sample Meshの位置と法線を接続し、表面に固定した毛の密度・長さ・太さを調整します。

パーティクルと毛 ​

VFX Graphのパーティクルは、移動する光や煙だけでなく、小さなポリゴンやメッシュを大量に配置するためにも使えます。
今回は、一本の毛を一つのパーティクルとして扱うことで、物体の表面に毛を生やす表現を実現します。

見本のFurStrandは、根元がY=0、先端がY=1のMeshです。根元を生成位置に置き、長さと太さをScaleで調整します。

Context毛の表現で行うこと
SpawnSingle Burstで必要な本数を一度に生成する
Initializeメッシュから位置と法線を取得し、根元と向きを決める
Update位置を動かさず、寿命による消滅も行わない
Output一本の毛のMeshを、指定した長さと太さで描画する

Mesh の表面からパーティクルを生成 ​

Graphを開き、SourceMeshからSample Meshまでの接続を確認してください。

SourceMeshには、ウサギの形状を持つBunnyHeight2を指定しています。
描画する毛のFurStrandではなく、パーティクルの生成位置を決めるために使用しています。

Sample Meshの設定は、Placement ModeがSurface、Surface CoordinatesがUniform、取得するOutputがPositionとNormalです。
入力するTriangleは三角形の番号、Squareは選んだ面の中で位置を求めるための二つの値です。

各設定の意味は公式ドキュメントでも確認できます。

Mesh Triangle Countで三角形の数を取得し、UInt型のRandomで有効な番号を選びます。
Vector2型のRandomは、それぞれ0〜1の値を生成します。
Sample Meshが、この値から三角形の内部の位置を求めます。

PositionをInitializeのSet Positionへ、NormalをSet AxisYへ接続することで、生成位置と法線をパーティクルに反映できます。
取得は生成時に一度だけ行っています。

今回は配置するMeshのローカル座標と、パーティクルのLocal空間をそろえています。
親のウサギとVisual Effectが同じTransformで回転するため、根元と毛が一緒に回ります。

毛の密度と方向 ​

毛の本数はHairCountで定義します。
この値はSingle BurstのCountに接続されており、1秒当たりの生成数ではありません。

現在の見本では、次の値をVisual Effectコンポーネントで指定しています。

ウサギHairCountHairLengthHairWidth
Few Fur(左)1000.1250.05
Many Fur(中央)25000.1250.05
Too Many Fur(右)100000.1250.05

Visual Effectコンポーネントで指定した値は、Graphの既定値より優先されます。
見本を再現するときは、Scene上の値を確認してください。

VFX Graphのプロパティ

Shader Graphと同様に、VFX Graphでもコンポーネントで指定した値が優先されます。
プロパティを外部公開することで、Visual Effectコンポーネントから値を変更できるようになります。

コードやアニメーションから値を更新することで、より柔軟に表現を制御できます。

このGraphは三角形を同じ確率で選びます。
三角形の面積に応じて選ぶ構成ではないため、細かく分割された部分では毛が密集しやすくなります。
サンプリング元のモデルによって、同じパラメーターでも異なる結果になりますので注意しましょう。

調整時の注意 ​

生成済みの毛の本数は、Countを編集しただけでは変わらない場合があります。
HairCountを変えた後は再度Playしなおしてください。

また、InitializeのCapacityは本数の上限です。
HairCountが収まる値にしましょう。
現在のGraphは65,536本まで扱えます。

毛の向きは、Initializeで保存したaxisYをOutputのOrientで使います。
OrientはFixed Axisとし、UpへaxisYを接続します。
これで毛のMeshのY軸が、ウサギの表面の法線に沿います。

Outputで設定する項目接続する値表示への影響
ScaleのYHairLength根元から先端までの長さ
ScaleのXとZHairWidth根元の太さ
OrientのUpaxisY表面に対する毛の向き

UpdateのInspectorでは、位置のIntegrationと角度のAngular IntegrationをNoneにし、Age ParticlesとReap Particlesを無効にしています。
位置と向きを保ち、時間経過で毛が消えないための設定です。
Updateの自動処理も確認してください。

より自然な表現を目指すには ​

毛の本数だけを増やすと、太い形が重なり、地肌や耳の形を覆ってしまいます。
まずHairWidthを小さくし、横から見た輪郭と正面から見た密度を確かめましょう。
長さも合わせて調整すると、元のウサギの形を残しやすくなります。

また、すべての毛が同じ長さで垂直に立つと、硬い印象になります。
基本の配置ができたら、生成時に毛ごとの長さを保存したり、法線から少し傾けたりする方法を考えてください。
乱数は生成時に決め、同じ毛の値が毎フレーム変わらないようにします。

照明を受ける毛には、見本のURP Lit Mesh Outputを使います。
地肌と毛の色をそろえても、法線や質感の設定によって明るさは変わります。

サンプルでは毛の法線を長手方向にそろえ、表面の向きに近い照明を受けるようにしています。
これは毛の配置を観察するための簡略化で、実際の毛に特有の光の反射まで再現するものではありません。
より自然な毛の表現を目指す場合は、毛の法線や反射特性を考慮したシェーダーを使用する必要があります。

注意点 ​

この見本は静的メッシュ用で、変形するメッシュには追従できません。
アニメーション変形に対応する場合は、毛ごとに選んだ三角形と面内の座標を保持し、変形したメッシュの三角形上の位置を再計算する必要があります。
14-4「Skinned Meshの変形に追従する」で、生成場所の保存とUpdateでの取得を実習します。

チェックリスト
  • SourceMeshと、Outputで描画する毛のMeshを区別できる。
  • Positionで根元を、Normalで毛の向きを設定できる。
  • 本数を変えた後に再生成し、回転中も根元がずれないことを確認できる。