161 lines
4.7 KiB
Plaintext
161 lines
4.7 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);
|
|
}
|
|
|
|
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 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: 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 := current_scene.camera.up;
|
|
right := current_scene.camera.right;
|
|
forward := 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(renderer, system.vertex_buffer, rendering_data.data, size_of(Particle_Vertex) * rendering_data.count);
|
|
}
|
|
}
|
|
|
|
render_particle_systems :: () {
|
|
for system: 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);
|
|
}
|
|
}
|
|
}
|
|
|