#version 450 layout(local_size_x = 128) in; struct EmitterParameters { vec4 angularMin; vec4 angularMax; vec4 lifeAndSizeRange; // min life, max life, min size, max size } struct ParticleData { vec4 position; vec4 rotation; vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; float life; uint textureIndex; } struct GenericData { //! Delta time float dt; //! Elapsed time of the application float elapsedTime; //! Viewport width of the scene (excluding imgui, that means smaller than window) uint viewportWidth; //! Ditto but for height uint viewportHeight; }; layout (set = 0, binding = 0) uniform GenericDataBuffer { GenericData data; } genericDataBuffer; layout (std430, set = 2, binding = 0) readonly buffer EmitterBuffer { EmitterParameters data; } emitterParams; layout (std430, set = 2, binding = 1) coherent restrict buffer ParticlesInputBuffer { ParticleData data[]; } inputParticles; // output buffer not needed // layout (std430, set = 2, binding = 2) coherent restrict buffer ParticlesOutputBuffer // { // ParticleData data[]; // } outputParticles; layout (std430, set = 2, binding = 3) coherent restrict buffer ParticlesFreelistBuffer { int freeCount; int freeIndices[]; } freelist; // push constants layout(std140, push_constant) uniform EmitterPushConstant { vec4 emitterPosition; uint emissionCount; } emitterPushConstant; uint pcg_hash(uint seed) { uint state = seed * 747796405u + 2891336453u; uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; return (word >> 22u) ^ word; } // Used to advance the PCG state. uint rand_pcg(inout uint rng_state) { uint state = rng_state; rng_state = rng_state * 747796405u + 2891336453u; uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; return (word >> 22u) ^ word; } // Advances the prng state and returns the corresponding random float. float rand(inout uint state) { uint x = rand_pcg(state); state = x; return float(x)*uintBitsToFloat(0x2f800004u); } void main() { uint emitterInvocationIndex = gl_GlobalInvocationID.x; if (emitterInvocationIndex >= emitterPushConstant.emissionCount) return; int freelistIndex = atomicAdd (freelist.freeCount, -1) - 1; if (freelistIndex < 0) atomicAdd (freelist.freeCount, 1); ParticleData particle; int index = freelist.freeIndices[freelistIndex]; particle.position = emitterPosition; particle.life = emitterParams.10.0f; particles[index] = particle; }