Skip to content

Commit a51e013

Browse files
committed
examples: particles: added gui settings for particle emitter
1 parent 85ca539 commit a51e013

File tree

6 files changed

+193
-26
lines changed

6 files changed

+193
-26
lines changed

TODO

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
- implement signals for node scripts
2-
- particle playground example
3-
- make nodes types more modular
41
- standard ECS library
2+
- implement signals for node scripts

examples/particles.cpp

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@
1111
#include <brenta/logger.hpp>
1212
#include <brenta/gui.hpp>
1313
#include <brenta/window.hpp>
14+
#include <brenta/mouse.hpp>
1415

1516
#include <bitset>
1617

1718
using namespace brenta;
1819

20+
void setup_gui(FrameBuffer &fb,
21+
ParticleEmitter *emitter);
22+
1923
int main()
2024
{
2125
const int SCR_WIDTH = 1280;
@@ -65,14 +69,134 @@ int main()
6569
.starting_spread(glm::vec3(3.0f, 10.0f, 3.0f))
6670
.starting_time_to_live(0.5f)
6771
.num_particles(1000)
68-
.spawn_rate(0.01f)
72+
.spawn_rate(0.99f)
6973
.scale(1.0f)
7074
.atlas_path("examples/assets/textures/particle_atlas.png")
7175
.atlas_width(8)
7276
.atlas_height(8)
7377
.atlas_index(3)
7478
.build();
7579

80+
81+
Mouse mouse = {};
82+
mouse.set_sensitivity(0.05f);
83+
84+
Input::add_mouse_callback("rotate_camera",
85+
[camera, &mouse](double xpos, double ypos)
86+
{
87+
// Rotate the camera
88+
if (Window::is_key_pressed(Key::LeftShift))
89+
{
90+
if (mouse.get_first())
91+
{
92+
mouse.set_x(xpos);
93+
mouse.set_y(ypos);
94+
mouse.set_first(false);
95+
}
96+
97+
float xoffset = xpos - mouse.get_x();
98+
float yoffset = mouse.get_y() - ypos;
99+
mouse.set_x(xpos);
100+
mouse.set_y(ypos);
101+
102+
auto sensitivity = mouse.get_sensitivity();
103+
xoffset *= sensitivity;
104+
yoffset *= sensitivity;
105+
106+
auto new_cam = camera->get_pos();
107+
try {
108+
Camera::Spherical scam = std::get<Camera::Spherical>(new_cam);
109+
scam.theta += yoffset * sensitivity;
110+
scam.phi += xoffset * sensitivity;
111+
112+
if (scam.theta <= 0.01f) scam.theta = 0.01f;
113+
if (scam.theta >= 3.13f) scam.theta = 3.13f;
114+
115+
camera->set_pos(scam);
116+
117+
} catch ([[maybe_unused]] const std::bad_variant_access& ex) {
118+
return;
119+
}
120+
}
121+
// translate the cam center
122+
else if (Window::is_key_pressed(Key::LeftControl))
123+
{
124+
if (mouse.get_first())
125+
{
126+
mouse.set_x(xpos);
127+
mouse.set_y(ypos);
128+
mouse.set_first(false);
129+
}
130+
131+
float xoffset = xpos - mouse.get_x();
132+
float yoffset = mouse.get_y() - ypos;
133+
mouse.set_x(xpos);
134+
mouse.set_y(ypos);
135+
136+
auto sensitivity = mouse.get_sensitivity();
137+
xoffset *= sensitivity * 0.3f;
138+
yoffset *= sensitivity * 0.3f;
139+
140+
auto new_cam = camera->get_pos();
141+
try {
142+
Camera::Spherical scam = std::get<Camera::Spherical>(new_cam);
143+
glm::vec3 world_pos = camera->get_transform().get_pos();
144+
// Local coordinate system
145+
glm::vec3 fixed_center =
146+
glm::vec3(scam.center.x, world_pos.y, scam.center.z);
147+
// Unit vectors
148+
glm::vec3 front =
149+
glm::normalize(world_pos - fixed_center);
150+
glm::vec3 right =
151+
glm::normalize(glm::cross(front, camera->get_world_up()));
152+
153+
scam.center += right * glm::vec3(xoffset);
154+
scam.center -= camera->get_world_up() * glm::vec3(yoffset);
155+
156+
camera->set_pos(scam);
157+
} catch ([[maybe_unused]] const std::bad_variant_access& ex) {
158+
return;
159+
}
160+
}
161+
// zoom the camera
162+
else if (Window::is_key_pressed(Key::LeftAlt))
163+
{
164+
if (mouse.get_first())
165+
{
166+
mouse.set_x(xpos);
167+
mouse.set_y(ypos);
168+
mouse.set_first(false);
169+
}
170+
171+
float xoffset = xpos - mouse.get_x();
172+
float yoffset = mouse.get_y() - ypos;
173+
mouse.set_x(xpos);
174+
mouse.set_y(ypos);
175+
176+
xoffset *= mouse.get_sensitivity();
177+
yoffset *= mouse.get_sensitivity();
178+
179+
auto new_cam = camera->get_pos();
180+
try {
181+
Camera::Spherical scam = std::get<Camera::Spherical>(new_cam);
182+
183+
scam.radius -= yoffset;
184+
if (scam.radius <= 0.1f) scam.radius = 0.1f;
185+
186+
camera->set_pos(scam);
187+
} catch ([[maybe_unused]] const std::bad_variant_access& ex) {
188+
return;
189+
}
190+
}
191+
else
192+
{
193+
mouse.set_first(true);
194+
}
195+
});
196+
197+
Gui::load_font();
198+
FrameBuffer fb(Window::get_width(), Window::get_height());
199+
76200
//
77201
// Render loop
78202
//
@@ -81,15 +205,53 @@ int main()
81205
{
82206
if (Window::is_key_pressed(Key::Escape))
83207
Window::close();
84-
208+
// TODO: movement
209+
210+
setup_gui(fb, &emitter);
211+
85212
Gl::set_color(Color::grey());
86213
Gl::clear();
87214

215+
fb.bind();
88216
emitter.update(Window::get_time().get_delta());
89217
emitter.render();
218+
fb.unbind();
90219

220+
Gui::render();
221+
91222
Window::poll_events();
92223
Window::swap_buffers();
93224
}
94225
return 0;
95226
}
227+
228+
void setup_gui(FrameBuffer &fb,
229+
ParticleEmitter *emitter)
230+
{
231+
Gui::new_frame(&fb, "particles");
232+
Gui::push_font();
233+
ImGui::Begin("Particle settings");
234+
235+
// Position and Movement
236+
ImGui::SliderFloat3("Starting position",
237+
&emitter->starting_position.x, -50.0f, 50.0f);
238+
ImGui::SliderFloat3("Starting velocity",
239+
&emitter->starting_velocity.x, -15.0f, 15.0f);
240+
ImGui::SliderFloat3("Starting spread",
241+
&emitter->starting_spread.x, 0.0f, 10.0f);
242+
243+
// Timing and Life
244+
ImGui::SliderFloat("Starting time to live",
245+
&emitter->starting_time_to_live, 0.0f, 15.0f);
246+
ImGui::SliderFloat("Spawn rate",
247+
&emitter->spawn_rate, 0.0f, 1.0f);
248+
249+
// Quantity and Appearance
250+
ImGui::SliderInt("Number of particles",
251+
&emitter->num_particles, 1, BRENTA_MAX_PARTICLES);
252+
ImGui::SliderFloat("Scale",
253+
&emitter->scale, 0.01f, 5.0f);
254+
255+
ImGui::End();
256+
Gui::pop_font();
257+
}

include/brenta/renderer/particles.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ struct ParticleEmitter::Config
8080
glm::vec3 starting_spread = {};
8181
float starting_time_to_live = 1.0f;
8282
int num_particles = BRENTA_MAX_PARTICLES;
83-
float spawn_rate = 0.01f;
83+
float spawn_rate = 0.99f;
8484
float scale = 1.0f;
8585
std::filesystem::path atlas_path = "";
8686
int atlas_width = 8;
@@ -96,6 +96,7 @@ class ParticleEmitter::Builder
9696
ParticleEmitter::Config conf = {};
9797

9898
public:
99+
99100
Builder &starting_position(glm::vec3 starting_position);
100101
Builder &starting_velocity(glm::vec3 starting_velocity);
101102
Builder &starting_spread(glm::vec3 starting_spread);

src/renderer/particles.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,18 @@ struct ParticleSettings {
3535

3636
ParticleEmitter::ParticleEmitter(Config conf)
3737
{
38-
this->starting_position = conf.starting_position;
39-
this->starting_velocity = conf.starting_velocity;
40-
this->starting_spread = conf.starting_spread;
38+
this->starting_position = conf.starting_position;
39+
this->starting_velocity = conf.starting_velocity;
40+
this->starting_spread = conf.starting_spread;
4141
this->starting_time_to_live = conf.starting_time_to_live;
42-
this->num_particles = conf.num_particles;
43-
this->spawn_rate = conf.spawn_rate;
44-
this->scale = conf.scale;
45-
this->atlas_width = conf.atlas_width;
46-
this->atlas_height = conf.atlas_height;
47-
this->atlas_index = conf.atlas_index;
48-
this->current_fbo_index = 0;
49-
this->cam = conf.cam;
42+
this->num_particles = conf.num_particles;
43+
this->spawn_rate = conf.spawn_rate;
44+
this->scale = conf.scale;
45+
this->atlas_width = conf.atlas_width;
46+
this->atlas_height = conf.atlas_height;
47+
this->atlas_index = conf.atlas_index;
48+
this->current_fbo_index = 0;
49+
this->cam = conf.cam;
5050

5151
// Load Texture Atlas
5252
this->atlas =
@@ -127,14 +127,14 @@ void ParticleEmitter::update(float delta_time)
127127
this->shader_update->use();
128128

129129
ParticleSettings settings = {
130-
.gravity = glm::vec3(0.0f, -9.81f, 0.0f),
131-
.deltaTime = delta_time,
132-
.emitterVel = this->starting_velocity,
133-
.emitterTTL = this->starting_time_to_live,
134-
.emitterPos = this->starting_position,
130+
.gravity = glm::vec3(0.0f, -9.81f, 0.0f),
131+
.deltaTime = delta_time,
132+
.emitterVel = this->starting_velocity,
133+
.emitterTTL = this->starting_time_to_live,
134+
.emitterPos = this->starting_position,
135135
.spawnProbability = this->spawn_rate,
136-
.emitterSpread = this->starting_spread,
137-
.__padding = 0.0f,
136+
.emitterSpread = this->starting_spread,
137+
.__padding = 0.0f,
138138
};
139139

140140
// ubo

src/renderer/shaders/c/particle_update_vs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ static const char* particle_update_vs = "#version 330 core\n"
2525
"void main()\n"
2626
"{\n"
2727
" float random = rand(vec2(deltaTime * float(gl_VertexID)));\n"
28-
" if (random < spawnProbability)\n"
28+
" if (random > spawnProbability)\n"
2929
" {\n"
30+
" // New particle\n"
3031
" outPosition = emitterPos;\n"
3132
" outVelocity = emitterVel + emitterSpread *\n"
3233
" vec3(rand(vec2(float(gl_VertexID + 1.0))) -0.5,\n"
@@ -38,12 +39,14 @@ static const char* particle_update_vs = "#version 330 core\n"
3839
"\n"
3940
" if (inTTL <= 0.0)\n"
4041
" {\n"
42+
" // Delete particle\n"
4143
" outPosition = inPosition;\n"
4244
" outVelocity = vec3(0.0);\n"
4345
" outTTL = -1.0;\n"
4446
" return;\n"
4547
" }\n"
4648
"\n"
49+
" // Update particle\n"
4750
" outTTL = inTTL - deltaTime;\n"
4851
"\n"
4952
" vec3 processed_velocity = inVelocity;\n"

src/renderer/shaders/particle_update.vs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ float rand(vec2 co);
2525
void main()
2626
{
2727
float random = rand(vec2(deltaTime * float(gl_VertexID)));
28-
if (random < spawnProbability)
28+
if (random > spawnProbability)
2929
{
30+
// New particle
3031
outPosition = emitterPos;
3132
outVelocity = emitterVel + emitterSpread *
3233
vec3(rand(vec2(float(gl_VertexID + 1.0))) -0.5,
@@ -38,12 +39,14 @@ void main()
3839

3940
if (inTTL <= 0.0)
4041
{
42+
// Delete particle
4143
outPosition = inPosition;
4244
outVelocity = vec3(0.0);
4345
outTTL = -1.0;
4446
return;
4547
}
4648

49+
// Update particle
4750
outTTL = inTTL - deltaTime;
4851

4952
vec3 processed_velocity = inVelocity;

0 commit comments

Comments
 (0)