Work in progress

The content of this page was not yet updated for Godot 4.2 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.

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

The problem with MeshInstance3D is that it is expensive to update their transform array. It is great for placing many static objects around the scene. But it is still difficult to move the objects around the scene.

To make each instance move in an interesting way, we will use a GPUParticles3D node. Particles take advantage of GPU acceleration by computing and setting the per-instance information in a Shader.

最初に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;
}

These functions come from the default ParticleProcessMaterial. They are used to generate a random number from each particle's RANDOM_SEED.

A unique thing about particle shaders is that some built-in variables are saved across frames. TRANSFORM, COLOR, and CUSTOM can all be accessed in the shader of the mesh, and also in the particle shader the next time it is run.

Next, setup your start() function. Particles shaders contain a start() function and a process() function.

The code in the start() function only runs when the particle system starts. The code in the process() function will always run.

We need to generate 4 random numbers: 3 to create a random position and one for the random offset of the swim cycle.

First, generate 4 seeds inside the start() function using the hash() function provided above:

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;

Remember, all this code so far goes inside the start() function.

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

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

Let's transform the fish by setting their VELOCITY in the start() function.

VELOCITY.z = 10.0;

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

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

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

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

You can also let each fish change its velocity over time if you set the velocity in the process() function.

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

CUSTOM.y = VELOCITY.z * 0.1;

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

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

Using a ParticleProcessMaterial you can make the fish behavior as simple or complex as you like. In this tutorial we only set Velocity, but in your own Shaders you can also set COLOR, rotation, scale (through TRANSFORM). Please refer to the Particles Shader Reference for more information on particle shaders.