#include "header.glsl"
#include "random.glsl"

layout (local_size_x = 1, local_size_y = 64, local_size_z = 1) in;

struct VertType {
	vec4 pos;
	vec4 colour;
	vec2 screen_offset;
	vec2 uv;
	int texid;
};

struct ParticleType {
	vec4 pos;
	vec4 vel;
	vec4 acc;
	vec4 colour;
	float random_pos;
	float random_vel;
	float random_time;
	float time_start;
	float duration;
	float size;
	int texid;
	int seed;
};

layout (binding = SSBO_PARTICLES_IN) readonly buffer ParticleBufferIn {
	ParticleType particles_in[];
};

layout (binding = SSBO_PARTICLES_OUT) writeonly buffer ParticleBufferOut {
	VertType vertices_out[];
};

layout (binding = SSBO_PARTICLES_LOOKUP) readonly buffer ParticleLookupIn {
	int lookup_in[];
};

layout (binding = UBO_PARTICLES_INFO) uniform ParticleInfo {
	float p_time;
	int p_size;
};

const vec2 QUADS[4] = {
	vec2(0, 0),
	vec2(1, 0),
	vec2(0, 1),
	vec2(1, 1)
};

void main() {
	ParticleType p = particles_in[lookup_in[gl_GlobalInvocationID.x]];
	
	int n = p.seed;
	rand_mix(n, int(gl_GlobalInvocationID.y));

	float t_total = p.duration + p.random_time * (rand_float(n)*2-1);
	float t = clamp(p_time - p.time_start, 0, t_total);
	float t_ratio = t / t_total;

	vec3 vel = p.vel.xyz + normalize(rand_vec3(n)*2-1) * p.random_vel;
	vec4 pos = vec4(p.pos.xyz + normalize(rand_vec3(n)*2-1) * p.random_pos + (vel + 0.5 * p.acc.xyz * t) * t, 1);
	vec4 colour = vec4(p.colour.rgb, p.colour.a * (1 - t_ratio));
	pos.z *= (pos.z > 0 ? 1 : 0);

	mat2 uv = mat2(rand_vec2(n), rand_vec2(n));
	uv = mat2(min(uv[0], uv[1]), max(uv[0], uv[1]));
	uint v_id = (gl_GlobalInvocationID.x * gl_WorkGroupSize.y * p_size + gl_GlobalInvocationID.y) * 4;
	
	for(int i = 0; i < 4; i++) {
		vertices_out[v_id+i].pos = pos;
		vertices_out[v_id+i].colour = colour;
		vertices_out[v_id+i].screen_offset = (QUADS[i]*2-1) * p.size;
		vertices_out[v_id+i].uv = QUADS[i] * (uv[1] - uv[0]) + uv[0];
		vertices_out[v_id+i].texid = p.texid;
	}
}