2 / 4 VFX Graphで毛を表現する
Sample Meshの位置と法線を接続し、表面に固定した毛の密度・長さ・太さを調整します。
パーティクルと毛
VFX Graphのパーティクルは、移動する光や煙だけでなく、小さなポリゴンやメッシュを大量に配置するためにも使えます。
今回は、一本の毛を一つのパーティクルとして扱うことで、物体の表面に毛を生やす表現を実現します。
見本のFurStrandは、根元がY=0、先端がY=1のMeshです。根元を生成位置に置き、長さと太さをScaleで調整します。
| Context | 毛の表現で行うこと |
|---|---|
| Spawn | Single 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コンポーネントで指定しています。
| ウサギ | HairCount | HairLength | HairWidth |
|---|---|---|---|
| Few Fur(左) | 100 | 0.125 | 0.05 |
| Many Fur(中央) | 2500 | 0.125 | 0.05 |
| Too Many Fur(右) | 10000 | 0.125 | 0.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のY | HairLength | 根元から先端までの長さ |
| ScaleのXとZ | HairWidth | 根元の太さ |
| OrientのUp | axisY | 表面に対する毛の向き |
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で毛の向きを設定できる。
- 本数を変えた後に再生成し、回転中も根元がずれないことを確認できる。