From 2c12446be8ee18e597a8c9b5d3bb018cbb11faa8 Mon Sep 17 00:00:00 2001 From: Daniel Bross Date: Fri, 11 Oct 2024 22:25:43 +0200 Subject: [PATCH] Particles file added --- core/particles.jai | 160 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 core/particles.jai diff --git a/core/particles.jai b/core/particles.jai new file mode 100644 index 0000000..8c80c21 --- /dev/null +++ b/core/particles.jai @@ -0,0 +1,160 @@ +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); +} + +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 game_state.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(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; + return particle_system; +} + +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: game_state.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 := game_state.camera.up; + right := game_state.camera.right; + forward := game_state.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(renderer, system.vertex_buffer, rendering_data.data, size_of(Particle_Vertex) * rendering_data.count); + } +} + +render_particle_systems :: () { + for system: game_state.current_scene.particle_systems { + prepare_particle_system_for_rendering(system); + + if system.particles.count > 0 { + push_cmd_set_draw_mode(renderer, .FILL); + push_cmd_set_depth_write(renderer, true); + push_cmd_set_cull_face(renderer, .BACK); + push_cmd_set_pipeline_state(renderer, system.pipeline); + + push_cmd_set_constant_buffer(renderer, 0, camera_buffer, .VERTEX); + + push_cmd_set_vertex_buffer(renderer, system.vertex_buffer); + + push_cmd_draw(renderer, system.particles.count * 6); + } + } +} +