Work in progress

The content of this page was not yet updated for Godot 4.5 and may be outdated. If you know how to improve this page or you can confirm that it's up to date, feel free to open a pull request.

パーティクルで数千の魚を制御する

MeshInstance3D の問題は、transform配列を更新するのにコストがかかることです。シーンの周囲に多くの静的オブジェクトを配置するのには最適です。ただしオブジェクトをシーン内で移動することは依然として困難です。

各インスタンスを興味深い方法で移動させるには、 GPUParticles3D ノードを使用します。パーティクルは、Shader でインスタンスごとの情報を計算および設定することにより、GPUアクセラレーションを利用します。

最初にParticlesノードを作成します。次に、Draw Passes の下で、パーティクルの Draw Pass 1Mesh に設定します。次に、[Process Material]の下に新しい ShaderMaterial を作成します。

shader_typeparticles に設定します。

shader_type particles

続いて、次の2つの関数を追加します:

float rand_from_seed(in uint seed) {
  int k;
  int s = int(seed);
  if (s == 0)
    s = 305420679;
  k = s / 127773;
  s = 16807 * (s - k * 127773) - 2836 * k;
  if (s < 0)
    s += 2147483647;
  seed = uint(s);
  return float(seed % uint(65536)) / 65535.0;
}

uint hash(uint x) {
  x = ((x >> uint(16)) ^ x) * uint(73244475);
  x = ((x >> uint(16)) ^ x) * uint(73244475);
  x = (x >> uint(16)) ^ x;
  return x;
}

これらの関数は、デフォルトの ParticleProcessMaterial から取得されます。これらは、各パーティクルの RANDOM_SEED から乱数を生成するために使用されます。

パーティクル シェーダーのユニークな点は、一部の組み込み変数がフレームを超えて保存されることです。 TRANSFORMCOLORCUSTOM はすべてメッシュのシェーダーでアクセスでき、次にパーティクルシェーダーを実行するときにもアクセスできます。

次に start() 関数を設定します。パーティクルシェーダーには、 start() 関数と process() 関数が含まれています。

start() 関数のコードは、パーティクルシステムが起動したときにのみ実行されます。 process() 関数のコードは常に実行されます。

次に4 つの乱数を生成する必要があります。3 つはランダムな位置を作成するためのもので、もう 1 つは水泳サイクルのランダムなオフセット用です。

まず、上記の hash() 関数を使用して start() 関数内に 4 つのシードを生成します。

uint alt_seed1 = hash(NUMBER + uint(1) + RANDOM_SEED);
uint alt_seed2 = hash(NUMBER + uint(27) + RANDOM_SEED);
uint alt_seed3 = hash(NUMBER + uint(43) + RANDOM_SEED);
uint alt_seed4 = hash(NUMBER + uint(111) + RANDOM_SEED);

次に、それらのシードを使用して rand_from_seed で乱数を生成します。

CUSTOM.x = rand_from_seed(alt_seed1);
vec3 position = vec3(rand_from_seed(alt_seed2) * 2.0 - 1.0,
                     rand_from_seed(alt_seed3) * 2.0 - 1.0,
                     rand_from_seed(alt_seed4) * 2.0 - 1.0);

最後に、位置情報を保持するtansformの一部である TRANSFORM[3].xyzposition を割り当てます。

TRANSFORM[3].xyz = position * 20.0;

これまでのコードはすべて start() 関数内に記述されていることに注意してください。

メッシュの頂点シェーダーは、前のチュートリアルとまったく同じままにすることができます。

これで、TRANSFORM に直接追加するか、VELOCITY に書き込むことで、各魚をフレームごとに個別に移動できます。

start() 関数で VELOCITY を設定して魚を変形させましょう。

VELOCITY.z = 10.0;

これは、すべてのパーティクル(または魚)が同じ速度を持つように VELOCITY を設定する最も基本的な方法です。

VELOCITY を設定するだけで、好きなように魚を泳がせることができます。たとえば、次のコードを試してください。

VELOCITY.z = cos(TIME + CUSTOM.x * 6.28) * 4.0 + 6.0;

これにより、各魚に 210 の間のユニークな速度が与えられます。

process() 関数で速度を設定すると、時間の経過とともに各魚の速度を変更することもできます。

前回のチュートリアルで CUSTOM.y を使用した場合、VELOCITY に基づいて遊泳アニメーションの速度を設定することもできます。CUSTOM.y を使用してください。

CUSTOM.y = VELOCITY.z * 0.1;

このコードは、次の動作を提供します:

../../../_images/scene.gif

ParticleProcessMaterial を使用すると、魚の挙動を好きなだけシンプルにしたり複雑にしたりできます。このチュートリアルでは速度のみを設定しますが、独自のシェーダーでは COLOR 、回転、スケール (TRANSFORM 経由) も設定できます。パーティクルシェーダーの詳細については、 パーティクルシェーダーリファレンス を参照してください。