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.

用粒子控制數千條魚

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

為了使每個實例以有趣的方式移動, 我們將使用一個 Particles 節點.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;
}

這些函式來自預設的 ParticlesMaterial,可以用來根據每個粒子的 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

使用 ParticlesMaterial 可以隨意讓魚的行為變得簡單或複雜。在本教學中,我們只設定了速度,但是在你自己的著色器中,你也可以設定 COLOR、旋轉、縮放(通過 TRANSFORM)。有關粒子著色器的更多資訊,請參閱:ref:《粒子著色器參考》 <doc_particle_shader>