Files
coven/core/particles.jai

169 lines
5.0 KiB
Plaintext

MAX_PARTICLES :: 2048;
Particle :: struct {
velocity: Vector3;
position: Vector3;
color: Vector4;
initial_lifetime: float;
lifetime: float;
initial_size: float;
size: float;
}
Particle_Vertex :: struct {
position: Vector3;
color: Vector4;
uv: Vector2;
}
Particle_System :: struct {
active: bool;
particles: [..] Particle;
pipeline: Pipeline_State_Handle;
owning_entity: *Entity;
time: float;
position: Vector3;
vertex_buffer: Buffer_Handle;
_locator: Bucket_Locator;
on_particle_update: (*Particle_System, float);
scene: *Scene;
}
create_particle_system :: (pipeline: Pipeline_State_Handle, update_func: (*Particle_System, float), owning_entity: *Entity = null, scene: *Scene = null, max_particles := MAX_PARTICLES) -> *Particle_System {
lvl := ifx scene == null then engine.current_scene else scene;
particle_system, locator := find_and_occupy_empty_slot(*scene.particle_systems);
particle_system._locator = locator;
particle_system.vertex_buffer = create_vertex_buffer(engine.renderer, null, xx (size_of(Particle_Vertex) * max_particles), stride=size_of(Particle_Vertex), mappable=true);
particle_system.pipeline = pipeline;
particle_system.on_particle_update = update_func;
particle_system.owning_entity = owning_entity;
particle_system.scene = scene;
return particle_system;
}
destroy_particle_system :: (system: *Particle_System) {
destroy_buffer(engine.renderer, system.vertex_buffer);
bucket_array_remove(*system.scene.particle_systems, system._locator);
}
spawn_particle :: (system: *Particle_System, position: Vector3, velocity: Vector3 = .{0,0,0}, size: float = 1.0, lifetime: float = 1.0, color: Vector4 = .{1,1,1,1}) {
particle: Particle;
particle.position = position;
particle.velocity = velocity;
particle.size = size;
particle.initial_size = size;
particle.lifetime = lifetime;
particle.initial_lifetime = lifetime;
particle.color = color;
array_add(*system.particles, particle);
}
update_particle_systems :: (dt: float) {
for *system: engine.current_scene.particle_systems {
if system.on_particle_update != null {
system.on_particle_update(system, dt);
}
}
}
update_particle_system :: (system: *Particle_System, dt: float) {
}
prepare_particle_system_for_rendering :: (system: Particle_System) {
up := engine.current_scene.camera.up;
right := engine.current_scene.camera.right;
forward := engine.current_scene.camera.forward;
rendering_data : [..] Particle_Vertex;
rendering_data.allocator = temp;
for p: system.particles {
//alpha := sin((p.lifetime / p.max_lifetime) * PI);
//color.w = alpha;
//size := p.size * alpha;
size := p.size;
color := p.color;
position := p.position - forward * (cast(float)it_index) * 0.01;
// Tri 0
{
v : Particle_Vertex;
v.uv = .{1, 1};
v.position = position + up * size + right * size;
v.color = color;
array_add(*rendering_data, v);
}
{
v : Particle_Vertex;
v.uv = .{1, 0};
v.position = position - up * size + right * size;
v.color = color;
array_add(*rendering_data, v);
}
{
v : Particle_Vertex;
v.uv = .{0, 0};
v.position = position - up * size - right * size;
v.color = color;
array_add(*rendering_data, v);
}
// Tri 1
{
v : Particle_Vertex;
v.uv = .{0, 0};
v.position = position - up * size - right * size;
v.color = color;
array_add(*rendering_data, v);
}
{
v : Particle_Vertex;
v.uv = .{1, 0};
v.position = position + up * size - right * size;
v.color = color;
array_add(*rendering_data, v);
}
{
v : Particle_Vertex;
v.uv = .{1, 1};
v.position = position + up * size + right * size;
v.color = color;
array_add(*rendering_data, v);
}
}
if rendering_data.count > 0 {
upload_data_to_buffer(engine.renderer, system.vertex_buffer, rendering_data.data, size_of(Particle_Vertex) * rendering_data.count);
}
}
render_particle_systems :: () {
for system: engine.current_scene.particle_systems {
prepare_particle_system_for_rendering(system);
if system.particles.count > 0 {
push_cmd_set_draw_mode(engine.renderer, .FILL);
push_cmd_set_depth_write(engine.renderer, true);
push_cmd_set_cull_face(engine.renderer, .BACK);
push_cmd_set_pipeline_state(engine.renderer, system.pipeline);
push_cmd_set_constant_buffer(engine.renderer, 0, engine.camera_buffer, .VERTEX);
push_cmd_set_vertex_buffer(engine.renderer, system.vertex_buffer);
push_cmd_draw(engine.renderer, system.particles.count * 6);
}
}
}