Skip to content
Snippets Groups Projects
generation.comp 3.06 KiB
#version 450 core
#extension GL_GOOGLE_include_directive : enable
#extension GL_ARB_separate_shader_objects : enable

layout(local_size_x = 256) in;

#include "physics.inc"
#include "particle.inc"

layout(set=0, binding=0, std430) buffer particleBuffer {
    particle_t particles [];
};

layout(set=1, binding=0, std430) readonly buffer randomBuffer {
    float randomData [];
};

#include "event.inc"

layout(set=1, binding=1, std430) buffer eventBuffer {
    event_t events [];
};

#include "smoke.inc"

layout(set=2, binding=0, std430) writeonly buffer smokeBuffer {
    smoke_t smokes [];
};

layout(set=2, binding=1, std430) buffer smokeIndexBuffer {
    uint smokeIndex;
};

layout( push_constant ) uniform constants{
    float t;
    float dt;
};

void main() {
    uint id = gl_GlobalInvocationID.x;

    if (id >= particles.length()) {
        return;
    }

    const float lifetime = particles[id].lifetime;

    if (lifetime > 0.0f) {
        return;
    }

    uint event_id = events.length();
    uint index = 0;

    for (uint i = 0; i < events.length(); i++) {
        const float start = events[i].startTime;

        if (((t - dt * 2) >= start) || (t < start)) {
            continue;
        }

        index = atomicAdd(events[i].index, 1);

        if (events[i].count > index) {
            event_id = i;
            break;
        } else {
            atomicAdd(events[i].index, -1);
        }
    }

    if (event_id >= events.length()) {
        return;
    }

    vec3 direction;
    if (dot(events[event_id].direction, events[event_id].direction) <= 0.0f) {
        direction = vec3(
            randomData[(id * 3 + 0) % randomData.length()],
            randomData[(id * 3 + 1) % randomData.length()],
            randomData[(id * 3 + 2) % randomData.length()]
        );
    } else {
        direction = events[event_id].direction;
    }

    const float v = events[event_id].velocity;

    vec3 velocity = vec3(0.0f);
    float size = events[event_id].size;

    if (events[event_id].parent < events.length()) {
        const uint spawnId = events[events[event_id].parent].pad0;

        if (spawnId < particles.length()) {
            particles[id].position = particles[spawnId].position;
            velocity += particles[spawnId].velocity;
            size = particles[spawnId].size;
        }
    }

    vec3 color = events[event_id].color;

    if (0 == index) {
        const uint sid = atomicAdd(smokeIndex, 1) % smokes.length();

        smokes[sid].position = particles[id].position;
        smokes[sid].size = size;
        smokes[sid].velocity = velocity;
        smokes[sid].scaling = v;
        smokes[sid].color = mix(color, vec3(1.0f), 0.75f);
        smokes[sid].eventID = event_id;
    }

    velocity += normalize(direction) * v;

    const float split = pow(1.0f / events[event_id].count, 1.0f / 3.0f);

    particles[id].lifetime = events[event_id].lifetime;
    particles[id].velocity = velocity;
    particles[id].size = size * split;
    particles[id].color = color;
    particles[id].mass = events[event_id].mass / events[event_id].count;

    events[event_id].pad0 = id;
}