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

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

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

ParticlesはGLES2では使用できません。代わりに CPUParticles を使用します。これはParticlesと同じことを行いますが、GPUアクセラレーションの恩恵は受けません。

`shader_type``particles` に設定します。

```shader_type particles
```

```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 ParticlesMaterial. 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 Spatial shader of the mesh, and also in the particle shader the next time it is run.

First we will distinguish between code that needs to be run only when the particle system starts and code that should always run. We want to give each fish a random position and a random animation offset when the system is first run. To do so, we wrap that code in an `if` statement that checks the built-in variable `RESTART` which becomes `true` for one frame when the particle system is restarted.

```void vertex() {
if (RESTART) {
//Initialization code goes here
} else {
//per-frame code goes here
}
}
```

まず、上記の `hash` 関数を使用して `RESTART` ブロック内に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);
```

```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);
```

```TRANSFORM[3].xyz = position * 20.0;
```

これまでのこのコードはすべて、`RESTART` ブロックの内部にあることに注意してください。

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

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

```VELOCITY.z = 10.0;
```

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

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

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

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

```CUSTOM.y = VELOCITY.z * 0.1;
```

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

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