quakeforge/libs/video/renderer/vulkan/shader/partupdate.comp

109 lines
2.7 KiB
Text
Raw Normal View History

#version 450
layout (constant_id = 0) const int MaxParticles = 2048;
layout (local_size_x = 1, local_size_y = 1) in;
struct Particle {
vec4 pos;
vec4 vel;
vec4 color;
float tex;
float ramp;
float scale;
float live;
};
struct Parameters {
vec4 drag; // [dx, dy, dz, grav scale]
vec4 ramp; // [rate, max, alpha rate, scale rate]
};
layout(std140, set = 0, binding = 0) buffer OutStates {
Particle particles[];
} outStates;
layout(std140, set = 0, binding = 1) buffer OutParameters {
Parameters parameters[];
} outParameters;
//doubles as VkDrawIndirectCommand
layout(std140, set = 0, binding = 2) buffer OutSystem {
uint vertexCount;
uint particleCount; //instanceCount
uint firstVertex;
uint firstInstance;
} outSystem;
layout(std140, set = 1, binding = 0) buffer InStates {
Particle particles[];
} inStates;
layout(std140, set = 1, binding = 1) buffer InParameters {
Parameters parameters[];
} inParameters;
//doubles as VkDrawIndirectCommand
layout(std140, set = 1, binding = 2) buffer InSystem {
uint vertexCount;
uint particleCount; //instanceCount
uint firstVertex;
uint firstInstance;
} inSystem;
layout(std140, set = 2, binding = 0) buffer NewStates {
Particle particles[];
} newStates;
layout(std140, set = 2, binding = 1) buffer NewParameters {
Parameters parameters[];
} newParameters;
//doubles as VkDrawIndirectCommand
layout(std140, set = 2, binding = 2) buffer NewSystem {
uint vertexCount;
uint particleCount; //instanceCount
uint firstVertex;
uint firstInstance;
} newSystem;
bool
is_dead (in Particle part, in Parameters parm)
{
if (part.live <= 0) {
return true;
}
if (part.ramp >= parm.ramp.y || part.color.a <= 0 || part.scale <= 0) {
return true;
}
return false;
}
void
main ()
{
uint j = 0;
// compact existing partles removing dead particles
for (uint i = 0; i < inSystem.particleCount; i++) {
if (is_dead (inStates.particles[i], inParameters.parameters[i])) {
continue;
}
outStates.particles[j] = inStates.particles[i];
outParameters.parameters[j] = inParameters.parameters[i];
j++;
}
// inject any new particles that aren't DOA
for (uint i = 0; i < newSystem.particleCount && j < MaxParticles; i++) {
if (is_dead (newStates.particles[i], newParameters.parameters[i])) {
continue;
}
outStates.particles[j] = newStates.particles[i];
outParameters.parameters[j] = newParameters.parameters[i];
j++;
}
outSystem.vertexCount = newSystem.vertexCount;
outSystem.particleCount = j;
outSystem.firstVertex = newSystem.firstVertex;
outSystem.firstInstance = newSystem.firstInstance;
}