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 的問題是,更新轉換陣列的代價很高。它非常適合在場景周圍放置許多靜態物件。但在場景中移動物體仍然很困難。

為了使每個實例以有趣的方式移動, 我們將使用一個 GPUParticles3D 節點.Particles通過在 Shader 中計算和設定每個實例的資訊來利用GPU加速。

首先建立一個 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;
}

這些函式來自預設的 ParticleProcessMaterial ,可以用來根據每個粒子的 RANDOM_SEED 生成亂數。

粒子著色器的一個獨特之處在於, 一些內建的變數可以跨影格保存. TRANSFORM , COLORCUSTOM 都可以在網格的Spatial shader 中存取, 下次運作時也可以在粒子著色器中存取.

接下來,設定您的 vertex 函式。粒子著色器只包含一個頂點函式,不包含其他函式。

“start()”函式中的程式碼僅在粒子系統啟動時運作。 “process()”函式中的程式碼將始終運作。

接下來, 我們需要生成4個亂數:3個用於建立一個隨機位置,1個用於游泳週期的隨機偏移量.

首先,使用上面提供的 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);

然後,使用這些種子生成亂數,使用 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;

記住,到目前為止,所有這些程式碼都位於 RESTART 塊中。

網格的頂點著色器, 可以完全複用前一教學中的.

現在每一影格你都可以單獨移動每條魚了,可以直接增加 TRANSFORM 也可以設定 VELOCITY

讓我們通過設定魚的 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 )。有關粒子著色器的更多資訊,請參閱 Particles Shader Reference