本系列文章是對 metalkit.org 上面MetalKit內容的全面翻譯和學習.
今天,我們將開始一個新系列,關於Metal
中的粒子系統.絕大多數時間,粒子都是小物體,我們總是不關心他們的幾何形狀.這讓他們適合於使用計算著色器,因為稍後我們將在粒子-粒子互動中使用粒度控制,這是一個用於展示通過計算著色器進行高度並行控制的例子.我們使用上一次的playground,就是從環境光遮蔽那裡開始.這個playground在這裡非常有用,因為它已經有一個CPU
傳遞到GPU
的time變數.我們從一個新的Shader.metal檔案開始,給一個漂亮的背景色:
#include <metal_stdlib>
using namespace metal;
kernel void compute(texture2d<float, access::write> output [[texture(0)]],
constant float &time [[buffer(0)]],
uint2 gid [[thread_position_in_grid]]) {
int width = output.get_width();
int height = output.get_height();
float2 uv = float2(gid) / float2(width, height);
output.write(float4(0.2, 0.5, 0.7, 1), gid);
}
複製程式碼
接著,讓我們建立一個粒子物件,只包含一個位置(中心)和半徑:
struct Particle {
float2 center;
float radius;
};
複製程式碼
我們還需要一個方法來獲取粒子在螢幕上的位置,那讓我們建立一個距離函式:
float distanceToParticle(float2 point, Particle p) {
return length(point - p.center) - p.radius;
}
複製程式碼
在核心中,在最後一行上面,讓我們一個新的粒子並將其放置在螢幕頂部,X
軸中間.設定半徑為0.05
:
float2 center = float2(0.5, time);
float radius = 0.05;
Particle p = Particle{center, radius};
複製程式碼
注意:我們使用
time
作為粒子的Y
座標,但這只是一個顯示基本運動的小技巧.很快,我們將用符合物理法則的座標來替換這個變數.
用下面程式碼替換核心的最後一行,並執行app.你會看到粒子以固定速率掉落:
float distance = distanceToParticle(uv, p);
float4 color = float4(1, 0.7, 0, 1);
if (distance > 0) { color = float4(0.2, 0.5, 0.7, 1); }
output.write(float4(color), gid);
複製程式碼
然而,這個粒子將永遠朝下運動.為了讓它停在底部,在建立粒子之前使用下面的條件:
float stop = 1 - radius;
if (time >= stop) { center.y = stop; }
else center.y = time;
複製程式碼
注意:
time
和uv
變數都在0-1
範圍內變化,這樣我們就建立一個stop
點,它就在螢幕正方邊緣一個粒子半徑的位置.
這是一個非常基本的碰撞檢測規則.如果你執行app,你將會看到粒子掉落並停上底部,像這樣:
下次,我們將更深入粒子動態效果,並實現物理運動法則.
原始碼source code已釋出在Github上.
下次見!