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.
Checking the stable version of the documentation...
用粒子控制数千条鱼¶
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 1”设置为你的 Mesh。然后在“Process Material”下创建一个新的 ShaderMaterial。
将 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 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);
最后,将 position
赋值给 TRANSFORM[3].xyz
,它是保存位置信息的变换的一部分。
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;
这将为每条鱼在 2
和 10
之间设置不同的速度。
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;
代码产生的效果如图:
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.