Skip to content

Commit 94dca5e

Browse files
committed
Particle emission and simulation up and running.
1 parent bb8777a commit 94dca5e

8 files changed

+121
-99
lines changed

src/main.cpp

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#undef min
1515
#undef max
1616
#define CAMERA_FAR_PLANE 1000.0f
17-
#define MAX_PARTICLES 100
17+
#define MAX_PARTICLES 128
1818
#define GRADIENT_SAMPLES 32
1919
#define LOCAL_SIZE 32
2020

@@ -86,6 +86,9 @@ class GPUParticleSystem : public dw::Application
8686
m_debug_draw.grid(m_main_camera->m_view_projection, 1.0f, 10.0f);
8787

8888
m_debug_draw.render(nullptr, m_width, m_height, m_main_camera->m_view_projection, m_main_camera->m_position);
89+
90+
m_pre_sim_idx = m_pre_sim_idx == 0 ? 1 : 0;
91+
m_post_sim_idx = m_post_sim_idx == 0 ? 1 : 0;
8992
}
9093

9194
// -----------------------------------------------------------------------------------------------------------------------------------
@@ -183,6 +186,7 @@ class GPUParticleSystem : public dw::Application
183186
{
184187
ImGui::InputFloat("Rotation", &m_rotation);
185188
ImGui::InputFloat3("Position", &m_position.x);
189+
ImGui::SliderFloat3("Velocity", &m_max_velocity.x, 0.1f, 5.0f);
186190
}
187191

188192
// -----------------------------------------------------------------------------------------------------------------------------------
@@ -198,7 +202,7 @@ class GPUParticleSystem : public dw::Application
198202
m_particle_program->set_uniform("u_Proj", m_main_camera->m_projection);
199203

200204
m_particle_data_ssbo->bind_base(0);
201-
m_alive_indices_post_sim_ssbo->bind_base(1);
205+
m_alive_indices_ssbo[m_post_sim_idx]->bind_base(1);
202206

203207
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_args_ssbo->handle());
204208

@@ -212,8 +216,7 @@ class GPUParticleSystem : public dw::Application
212216
m_particle_initialize_program->use();
213217

214218
m_dead_indices_ssbo->bind_base(0);
215-
m_alive_indices_pre_sim_ssbo->bind_base(1);
216-
m_counters_ssbo->bind_base(2);
219+
m_counters_ssbo->bind_base(1);
217220

218221
m_particle_initialize_program->set_uniform("u_MaxParticles", MAX_PARTICLES);
219222

@@ -230,7 +233,9 @@ class GPUParticleSystem : public dw::Application
230233

231234
int32_t rate = glm::max(1, int32_t(float(m_emission_rate) * float(m_delta_seconds)));
232235
m_particle_update_kickoff_program->set_uniform("u_ParticlesPerFrame", rate);
233-
236+
m_particle_update_kickoff_program->set_uniform("u_PreSimIdx", m_pre_sim_idx);
237+
m_particle_update_kickoff_program->set_uniform("u_PostSimIdx", m_post_sim_idx);
238+
234239
m_particle_data_ssbo->bind_base(0);
235240
m_dispatch_emission_indirect_args_ssbo->bind_base(1);
236241
m_dispatch_simulation_indirect_args_ssbo->bind_base(2);
@@ -251,10 +256,11 @@ class GPUParticleSystem : public dw::Application
251256
m_particle_emission_program->set_uniform("u_EmitterPosition", m_position);
252257
m_particle_emission_program->set_uniform("u_EmitterVelocity", m_max_velocity);
253258
m_particle_emission_program->set_uniform("u_EmitterLifetime", m_max_lifetime);
259+
m_particle_emission_program->set_uniform("u_PreSimIdx", m_pre_sim_idx);
254260

255261
m_particle_data_ssbo->bind_base(0);
256262
m_dead_indices_ssbo->bind_base(1);
257-
m_alive_indices_pre_sim_ssbo->bind_base(2);
263+
m_alive_indices_ssbo[m_pre_sim_idx]->bind_base(2);
258264
m_counters_ssbo->bind_base(3);
259265

260266
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, m_dispatch_emission_indirect_args_ssbo->handle());
@@ -271,19 +277,21 @@ class GPUParticleSystem : public dw::Application
271277
m_particle_simulation_program->use();
272278

273279
m_particle_simulation_program->set_uniform("u_DeltaTime", float(m_delta_seconds));
280+
m_particle_simulation_program->set_uniform("u_PreSimIdx", m_pre_sim_idx);
281+
m_particle_simulation_program->set_uniform("u_PostSimIdx", m_post_sim_idx);
274282

275283
m_particle_data_ssbo->bind_base(0);
276284
m_dead_indices_ssbo->bind_base(1);
277-
m_alive_indices_pre_sim_ssbo->bind_base(2);
278-
m_alive_indices_post_sim_ssbo->bind_base(3);
285+
m_alive_indices_ssbo[m_pre_sim_idx]->bind_base(2);
286+
m_alive_indices_ssbo[m_post_sim_idx]->bind_base(3);
279287
m_draw_indirect_args_ssbo->bind_base(4);
280288
m_counters_ssbo->bind_base(5);
281289

282290
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, m_dispatch_simulation_indirect_args_ssbo->handle());
283291

284292
glDispatchComputeIndirect(0);
285293

286-
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
294+
glMemoryBarrier(GL_ALL_BARRIER_BITS);
287295
}
288296

289297
// -----------------------------------------------------------------------------------------------------------------------------------
@@ -325,7 +333,7 @@ class GPUParticleSystem : public dw::Application
325333
}
326334

327335
// Create general shader program
328-
dw::gl::Shader* shaders[] = { m_particle_initialize_cs.get() };
336+
dw::gl::Shader* shaders[] = { m_particle_initialize_cs.get() };
329337
m_particle_initialize_program = std::make_unique<dw::gl::Program>(1, shaders);
330338

331339
if (!m_particle_initialize_program)
@@ -405,14 +413,14 @@ class GPUParticleSystem : public dw::Application
405413
glm::vec4 color;
406414
};
407415

408-
m_draw_indirect_args_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * 4, nullptr);
409-
m_dispatch_emission_indirect_args_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * 3, nullptr);
416+
m_draw_indirect_args_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * 4, nullptr);
417+
m_dispatch_emission_indirect_args_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * 3, nullptr);
410418
m_dispatch_simulation_indirect_args_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * 3, nullptr);
411-
m_particle_data_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(Particle) * MAX_PARTICLES, nullptr);
412-
m_alive_indices_pre_sim_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * MAX_PARTICLES, nullptr);
413-
m_alive_indices_post_sim_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * MAX_PARTICLES, nullptr);
414-
m_dead_indices_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * MAX_PARTICLES, nullptr);
415-
m_counters_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * 5, nullptr);
419+
m_particle_data_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(Particle) * MAX_PARTICLES, nullptr);
420+
m_alive_indices_ssbo[0] = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * MAX_PARTICLES, nullptr);
421+
m_alive_indices_ssbo[1] = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * MAX_PARTICLES, nullptr);
422+
m_dead_indices_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * MAX_PARTICLES, nullptr);
423+
m_counters_ssbo = std::make_unique<dw::gl::ShaderStorageBuffer>(GL_STATIC_DRAW, sizeof(int32_t) * 5, nullptr);
416424

417425
return true;
418426
}
@@ -487,8 +495,7 @@ class GPUParticleSystem : public dw::Application
487495
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_dispatch_emission_indirect_args_ssbo;
488496
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_dispatch_simulation_indirect_args_ssbo;
489497
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_particle_data_ssbo;
490-
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_alive_indices_pre_sim_ssbo;
491-
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_alive_indices_post_sim_ssbo;
498+
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_alive_indices_ssbo[2];
492499
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_dead_indices_ssbo;
493500
std::unique_ptr<dw::gl::ShaderStorageBuffer> m_counters_ssbo;
494501

@@ -514,16 +521,18 @@ class GPUParticleSystem : public dw::Application
514521

515522
// Particle settings
516523
uint32_t m_max_active_particles = 0; // Max Lifetime * Emission Rate
517-
uint32_t m_emission_rate = 100; // Particles per second
524+
uint32_t m_emission_rate = 100; // Particles per second
518525
float m_min_lifetime = 0.0f; // Seconds
519526
float m_max_lifetime = 3.0f; // Seconds
520-
glm::vec3 m_min_velocity = glm::vec3(0.0f);
521-
glm::vec3 m_max_velocity = glm::vec3(0.0f, 1.0f, 0.0f);
527+
glm::vec3 m_min_velocity = glm::vec3(0.0f);
528+
glm::vec3 m_max_velocity = glm::vec3(0.0f, 2.0f, 0.0f);
522529
bool m_affected_by_gravity = false;
523530
PropertyChangeType m_color_mode = PROPERTY_CONSTANT;
524531
PropertyChangeType m_scale_mode = PROPERTY_CONSTANT;
525532
glm::vec3 m_position = glm::vec3(0.0f);
526533
float m_rotation = 0.0f;
534+
int32_t m_pre_sim_idx = 0;
535+
int32_t m_post_sim_idx = 1;
527536
};
528537

529538
DW_DECLARE_MAIN(GPUParticleSystem)

src/shader/particle_emission_cs.glsl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// INPUTS -----------------------------------------------------------
99
// ------------------------------------------------------------------
1010

11-
layout (local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
11+
layout(local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
1212

1313
// ------------------------------------------------------------------
1414
// UNIFORMS ---------------------------------------------------------
@@ -22,33 +22,37 @@ struct Particle
2222
vec4 color;
2323
};
2424

25-
uniform vec3 u_EmitterPosition;
26-
uniform vec3 u_EmitterVelocity;
25+
uniform vec3 u_EmitterPosition;
26+
uniform vec3 u_EmitterVelocity;
2727
uniform float u_EmitterLifetime;
28+
uniform int u_PreSimIdx;
2829

2930
layout(std430, binding = 0) buffer ParticleData_t
3031
{
3132
Particle particles[];
32-
} ParticleData;
33+
}
34+
ParticleData;
3335

3436
layout(std430, binding = 1) buffer ParticleDeadIndices_t
3537
{
3638
uint indices[];
37-
} DeadIndices;
39+
}
40+
DeadIndices;
3841

3942
layout(std430, binding = 2) buffer ParticleAlivePreSimIndices_t
4043
{
4144
uint indices[];
42-
} AliveIndicesPreSim;
45+
}
46+
AliveIndicesPreSim;
4347

4448
layout(std430, binding = 3) buffer Counters_t
4549
{
4650
uint dead_count;
47-
uint alive_pre_sim_count;
48-
uint alive_post_sim_count;
51+
uint alive_count[2];
4952
uint simulation_count;
5053
uint emission_count;
51-
} Counters;
54+
}
55+
Counters;
5256

5357
// ------------------------------------------------------------------
5458
// FUNCTIONS --------------------------------------------------------
@@ -62,7 +66,7 @@ uint pop_dead_index()
6266

6367
void push_alive_index(uint index)
6468
{
65-
uint insert_idx = atomicAdd(Counters.alive_pre_sim_count, 1);
69+
uint insert_idx = atomicAdd(Counters.alive_count[u_PreSimIdx], 1);
6670
AliveIndicesPreSim.indices[insert_idx] = index;
6771
}
6872

@@ -80,7 +84,7 @@ void main()
8084

8185
ParticleData.particles[particle_index].position.xyz = u_EmitterPosition;
8286
ParticleData.particles[particle_index].velocity.xyz = u_EmitterVelocity;
83-
ParticleData.particles[particle_index].lifetime.xy = vec2(0.0, u_EmitterLifetime);
87+
ParticleData.particles[particle_index].lifetime.xy = vec2(0.0, u_EmitterLifetime);
8488

8589
push_alive_index(particle_index);
8690
}

src/shader/particle_initialize_cs.glsl

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// INPUTS -----------------------------------------------------------
99
// ------------------------------------------------------------------
1010

11-
layout (local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
11+
layout(local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
1212

1313
// ------------------------------------------------------------------
1414
// UNIFORMS ---------------------------------------------------------
@@ -17,21 +17,17 @@ layout (local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
1717
layout(std430, binding = 0) buffer ParticleDeadIndices_t
1818
{
1919
uint indices[];
20-
} DeadIndices;
20+
}
21+
DeadIndices;
2122

22-
layout(std430, binding = 1) buffer ParticleAlivePreSimIndices_t
23-
{
24-
uint indices[];
25-
} AliveIndicesPreSim;
26-
27-
layout(std430, binding = 2) buffer ParticleCounters_t
23+
layout(std430, binding = 1) buffer ParticleCounters_t
2824
{
2925
uint dead_count;
30-
uint alive_pre_sim_count;
31-
uint alive_post_sim_count;
26+
uint alive_count[2];
3227
uint simulation_count;
3328
uint emission_count;
34-
} Counters;
29+
}
30+
Counters;
3531

3632
uniform int u_MaxParticles;
3733

@@ -46,8 +42,9 @@ void main()
4642
if (index == 0)
4743
{
4844
// Initialize counts
49-
Counters.dead_count = u_MaxParticles - 1;
50-
Counters.alive_pre_sim_count = 0;
45+
Counters.dead_count = u_MaxParticles;
46+
Counters.alive_count[0] = 0;
47+
Counters.alive_count[1] = 0;
5148
}
5249

5350
DeadIndices.indices[index] = index;

src/shader/particle_simulation_cs.glsl

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// INPUTS -----------------------------------------------------------
99
// ------------------------------------------------------------------
1010

11-
layout (local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
11+
layout(local_size_x = LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
1212

1313
// ------------------------------------------------------------------
1414
// UNIFORMS ---------------------------------------------------------
@@ -25,49 +25,56 @@ struct Particle
2525
layout(std430, binding = 0) buffer ParticleData_t
2626
{
2727
Particle particles[];
28-
} ParticleData;
28+
}
29+
ParticleData;
2930

3031
layout(std430, binding = 1) buffer ParticleDeadIndices_t
3132
{
3233
uint indices[];
33-
} DeadIndices;
34+
}
35+
DeadIndices;
3436

3537
layout(std430, binding = 2) buffer ParticleAlivePreSimIndices_t
3638
{
3739
uint indices[];
38-
} AliveIndicesPreSim;
40+
}
41+
AliveIndicesPreSim;
3942

4043
layout(std430, binding = 3) buffer ParticleAlivePostSimIndices_t
4144
{
4245
uint indices[];
43-
} AliveIndicesPostSim;
46+
}
47+
AliveIndicesPostSim;
4448

4549
layout(std430, binding = 4) buffer ParticleDrawArgs_t
4650
{
4751
uint count;
4852
uint instance_count;
4953
uint first;
5054
uint base_instance;
51-
} ParticleDrawArgs;
55+
}
56+
ParticleDrawArgs;
5257

5358
layout(std430, binding = 5) buffer ParticleCounters_t
5459
{
5560
uint dead_count;
56-
uint alive_pre_sim_count;
57-
uint alive_post_sim_count;
61+
uint alive_count[2];
5862
uint simulation_count;
5963
uint emission_count;
60-
} Counters;
64+
}
65+
Counters;
6166

6267
uniform float u_DeltaTime;
68+
uniform int u_PreSimIdx;
69+
uniform int u_PostSimIdx;
6370

6471
// ------------------------------------------------------------------
6572
// FUNCTIONS --------------------------------------------------------
6673
// ------------------------------------------------------------------
6774

6875
void push_dead_index(uint index)
6976
{
70-
uint insert_idx = atomicAdd(Counters.dead_count, 1);
77+
uint insert_idx = atomicAdd(Counters.dead_count, 1);
7178
DeadIndices.indices[insert_idx] = index;
7279
}
7380

@@ -79,13 +86,13 @@ uint pop_dead_index()
7986

8087
void push_alive_index(uint index)
8188
{
82-
uint insert_idx = atomicAdd(Counters.alive_post_sim_count, 1);
89+
uint insert_idx = atomicAdd(Counters.alive_count[u_PostSimIdx], 1);
8390
AliveIndicesPostSim.indices[insert_idx] = index;
8491
}
8592

8693
uint pop_alive_index()
8794
{
88-
uint index = atomicAdd(Counters.alive_pre_sim_count, -1);
95+
uint index = atomicAdd(Counters.alive_count[u_PreSimIdx], -1);
8996
return AliveIndicesPreSim.indices[index - 1];
9097
}
9198

0 commit comments

Comments
 (0)