git.iko.soy/metal-metaballs
on master help sign in
Momoized a few calculations (complexity is still the same though).
67fc9a0vinivendra
PixelImage/shaders.metal+17−18
@@ -3,11 +3,7 @@
3
3
4using namespace metal;
4using namespace metal;
5
5
6−kernel void
7− drawMetaballs(texture2d<float, access::write> outTexture[[texture(0)]],
6+kernel void drawMetaballs(texture2d<float, access::write> outTexture[[texture(0)]], constant float *edgesBuffer[[buffer(1)]], constant float *metaballBuffer[[buffer(0)]], uint2 gid[[thread_position_in_grid]]) {
8− constant float *edgesBuffer[[buffer(1)]],
9− constant float *metaballBuffer[[buffer(0)]],
10− uint2 gid[[thread_position_in_grid]]) {
11
7
12 uint numberOfMetaballs = metaballBuffer[0];
8 uint numberOfMetaballs = metaballBuffer[0];
13 uint metaballArraySize = numberOfMetaballs * 2 + 1;
9 uint metaballArraySize = numberOfMetaballs * 2 + 1;
@@ -16,19 +12,22 @@ kernel void
16
12
17 uint i, j, x, y;
13 uint i, j, x, y;
18
14
19− for (i = 1, x = 0; i < metaballArraySize; i += 2, x += 1) {
15+ float metaballDistances[10];
20− for (j = i + 2, y = x + 1; j < metaballArraySize; j += 2, y += 1) {
16+ float2 metaballDirections[10];
21− float2 metaball1 = float2(metaballBuffer[i], metaballBuffer[i + 1]);
22
17
18+ for (i = 1, x = 0; i < metaballArraySize; i += 2, x += 1) {
23− float2 metaball2 = float2(metaballBuffer[j], metaballBuffer[j + 1]);
19+ float2 metaball = float2(metaballBuffer[i], metaballBuffer[i + 1]);
24−
25− float2 metaball1Vector
26− = float2(metaball1.x - gid.x, metaball1.y - gid.y);
20+ float2 vector = float2(metaball.x - gid.x, metaball.y - gid.y);
27− float2 metaball2Vector
21+ float squaredDistance = dot(vector, vector);
28− = float2(metaball2.x - gid.x, metaball2.y - gid.y);
22+ float realDistance = sqrt(squaredDistance);
23+ metaballDistances[x] = squaredDistance;
24+ metaballDirections[x] = vector/realDistance;
25+ }
29
26
30− float value1 = 2048 / (dot(metaball1Vector, metaball1Vector) + 1);
27+ for (i = 1, x = 0; i < metaballArraySize; i += 2, x += 1) {
31− float value2 = 2048 / (dot(metaball2Vector, metaball2Vector) + 1);
28+ for (j = i + 2, y = x + 1; j < metaballArraySize; j += 2, y += 1) {
29+ float value1 = 2048 / (metaballDistances[x] + 1);
30+ float value2 = 2048 / (metaballDistances[y] + 1);
32
31
33 float v = value1 + value2;
32 float v = value1 + value2;
34
33
@@ -36,8 +35,8 @@ kernel void
36
35
37 char edgeIndex = y * numberOfMetaballs + x;
36 char edgeIndex = y * numberOfMetaballs + x;
38 float edgeWeight = edgesBuffer[edgeIndex];
37 float edgeWeight = edgesBuffer[edgeIndex];
39− float2 direction1 = normalize(metaball1Vector);
38+ float2 direction1 = metaballDirections[x];
40− float2 direction2 = normalize(metaball2Vector);
39+ float2 direction2 = metaballDirections[y];
41
40
42 float cosine = dot(direction1, direction2);
41 float cosine = dot(direction1, direction2);
43
42