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) -> *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, 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); } } }