Files
Towards/external/loft/examples/viewer/shaders/Particles.comp
T
Martin Slachta a04f0dc262 initial
2026-07-18 14:31:15 +02:00

73 lines
1.8 KiB
Plaintext

#version 450
struct Particle {
vec4 position;
vec4 velocity;
vec4 gradient_pos;
};
layout(std140, binding = 0) buffer ParticleBuffer {
Particle particles[];
};
layout (local_size_x = 256) in;
vec2 attraction(vec2 pos, vec2 attractPos)
{
vec2 delta = attractPos - pos;
const float damp = 0.5;
float dDampedDot = dot(delta, delta) + damp;
float invDist = 1.0f / sqrt(dDampedDot);
float invDistCubed = invDist*invDist*invDist;
return delta * invDistCubed * 0.0035;
}
vec2 repulsion(vec2 pos, vec2 attractPos)
{
vec2 delta = attractPos - pos;
float targetDistance = sqrt(dot(delta, delta));
return delta * (1.0 / (targetDistance * targetDistance * targetDistance)) * -0.000035;
}
void main()
{
uint particle_count = 1000;
float dest_x = 0.0f;
float dest_y = 0.0f;
float delta_time = 0.001;
// Current SSBO index
uint index = gl_GlobalInvocationID.x;
// Don't try to write beyond particle count
if (index >= particle_count)
return;
// Read position and velocity
vec2 vVel = particles[index].velocity.xy;
vec2 vPos = particles[index].position.xy;
vec2 destPos = vec2(dest_x, dest_y);
vec2 delta = destPos - vPos;
float targetDistance = sqrt(dot(delta, delta));
vVel += repulsion(vPos, destPos.xy) * 0.05;
// Move by velocity
vPos += vVel * delta_time;
// collide with boundary
if ((vPos.x < -1.0) || (vPos.x > 1.0) || (vPos.y < -1.0) || (vPos.y > 1.0))
vVel = (-vVel * 0.1) + attraction(vPos, destPos) * 12;
else
particles[index].position.xy = vPos;
// Write back
particles[index].velocity.xy = vVel;
particles[index].gradient_pos.x += 0.02 * delta_time;
if (particles[index].gradient_pos.x > 1.0)
particles[index].gradient_pos.x -= 1.0;
particles[index].position = vec4(0.0, index, index, 1.0f);
}