#include "particle.h" #include "types.h" #include "shader.h" #include #include void respawn_particle(struct particle *particle, struct object object, v2 offset) { f32 random = ((rand() % 100) - 50) / 10.0f; particle->pos = addf_v2(add_v2(object.pos, offset), random); particle->vel = scale_v2(object.vel, 0.1f); random = 0.5f + ((rand() % 100) / 100.0f); particle->color = (v4){random, random, random, 1.0f}; particle->life = 1.0f; } i32 find_unused_particle(struct particle_generator generator) { f32 min = FLT_MAX; i32 mini = 0; for (i32 i = 0; i < MAX_PARTICLES; i++) { f32 life = generator.particles[i].life; if (life <= 0.0f) { return i; } else if (life < min) { min = life; mini = i; } } return mini; } struct particle_generator init_generator(i32 new, u32 shader, u32 texture) { struct particle_generator generator = {0}; reset_particles(&generator); generator.new = new; generator.shader = shader; generator.texture = texture; f32 vertices[] = { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f }; u32 vao, vbo; glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindVertexArray(vao); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, 0, 4 * sizeof(f32), 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); generator.vao = vao; return generator; } void update_particles(struct particle_generator *generator, struct object object, f32 dt, v2 offset) { for (i32 i = 0; i < generator->new; i++) { i32 unused = find_unused_particle(*generator); respawn_particle(generator->particles + unused, object, offset); } for (i32 i = 0; i < MAX_PARTICLES; i++) { struct particle *particle = generator->particles + i; particle->life -= dt; if (particle->life > 0.0f) { particle->pos = sub_v2(particle->pos, scale_v2(particle->vel, dt)); particle->color.w -= dt * 2.0f; } } } void render_particles(struct particle_generator generator) { glBlendFunc(GL_SRC_ALPHA, GL_ONE); glUseProgram(generator.shader); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, generator.texture); glBindVertexArray(generator.vao); for (i32 i = 0; i < MAX_PARTICLES; i++) { struct particle *particle = generator.particles + i; if (particle->life > 0.0f) { uniform_v2(generator.shader, "offset", particle->pos); uniform_v4(generator.shader, "color", particle->color); glDrawArrays(GL_TRIANGLES, 0, 6); } } glBindVertexArray(0); glUseProgram(0); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } void reset_particles(struct particle_generator *generator) { for (i32 i = 0; i < MAX_PARTICLES; i++) generator->particles[i] = (struct particle)default_particle; }