Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

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

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 経由) も設定できます。パーティクルシェーダーの詳細については、 パーティクルシェーダーリファレンス を参照してください。