#include using namespace metal; struct tint_symbol_1 { float2 a_particlePos [[attribute(0)]]; float2 a_particleVel [[attribute(1)]]; float2 a_pos [[attribute(2)]]; }; struct tint_symbol_2 { float4 value [[position]]; }; struct tint_symbol_3 { float4 value [[color(0)]]; }; struct Particle { /* 0x0000 */ packed_float2 pos; /* 0x0008 */ packed_float2 vel; }; struct SimParams { /* 0x0000 */ float deltaT; /* 0x0004 */ float rule1Distance; /* 0x0008 */ float rule2Distance; /* 0x000c */ float rule3Distance; /* 0x0010 */ float rule1Scale; /* 0x0014 */ float rule2Scale; /* 0x0018 */ float rule3Scale; }; struct tint_array_wrapper { /* 0x0000 */ Particle arr[5]; }; struct Particles { /* 0x0000 */ tint_array_wrapper particles; }; vertex tint_symbol_2 vert_main(tint_symbol_1 tint_symbol [[stage_in]]) { float2 const a_particlePos = tint_symbol.a_particlePos; float2 const a_particleVel = tint_symbol.a_particleVel; float2 const a_pos = tint_symbol.a_pos; float angle = -(atan2(a_particleVel.x, a_particleVel.y)); float2 pos = float2(((a_pos.x * cos(angle)) - (a_pos.y * sin(angle))), ((a_pos.x * sin(angle)) + (a_pos.y * cos(angle)))); tint_symbol_2 const tint_symbol_5 = {.value=float4((pos + a_particlePos), 0.0f, 1.0f)}; return tint_symbol_5; } fragment tint_symbol_3 frag_main() { tint_symbol_3 const tint_symbol_6 = {.value=float4(1.0f, 1.0f, 1.0f, 1.0f)}; return tint_symbol_6; } kernel void comp_main(uint3 gl_GlobalInvocationID [[thread_position_in_grid]], constant SimParams& params [[buffer(0)]], device Particles& particlesA [[buffer(1)]], device Particles& particlesB [[buffer(2)]]) { uint index = gl_GlobalInvocationID.x; if ((index >= 5u)) { return; } float2 vPos = particlesA.particles.arr[index].pos; float2 vVel = particlesA.particles.arr[index].vel; float2 cMass = float2(0.0f, 0.0f); float2 cVel = float2(0.0f, 0.0f); float2 colVel = float2(0.0f, 0.0f); int cMassCount = 0; int cVelCount = 0; float2 pos = 0.0f; float2 vel = 0.0f; for(uint i = 0u; (i < 5u); i = (i + 1u)) { if ((i == index)) { continue; } pos = particlesA.particles.arr[i].pos.xy; vel = particlesA.particles.arr[i].vel.xy; if ((distance(pos, vPos) < params.rule1Distance)) { cMass = (cMass + pos); cMassCount = (cMassCount + 1); } if ((distance(pos, vPos) < params.rule2Distance)) { colVel = (colVel - (pos - vPos)); } if ((distance(pos, vPos) < params.rule3Distance)) { cVel = (cVel + vel); cVelCount = (cVelCount + 1); } } if ((cMassCount > 0)) { cMass = ((cMass / float2(float(cMassCount), float(cMassCount))) - vPos); } if ((cVelCount > 0)) { cVel = (cVel / float2(float(cVelCount), float(cVelCount))); } vVel = (((vVel + (cMass * params.rule1Scale)) + (colVel * params.rule2Scale)) + (cVel * params.rule3Scale)); vVel = (normalize(vVel) * clamp(length(vVel), 0.0f, 0.100000001f)); vPos = (vPos + (vVel * params.deltaT)); if ((vPos.x < -1.0f)) { vPos.x = 1.0f; } if ((vPos.x > 1.0f)) { vPos.x = -1.0f; } if ((vPos.y < -1.0f)) { vPos.y = 1.0f; } if ((vPos.y > 1.0f)) { vPos.y = -1.0f; } particlesB.particles.arr[index].pos = vPos; particlesB.particles.arr[index].vel = vVel; return; }