Skip to content

Commit

Permalink
Particle system is complete. Rejoice!
Browse files Browse the repository at this point in the history
  • Loading branch information
reduz committed Apr 9, 2017
1 parent 6075dfe commit 4286aef
Show file tree
Hide file tree
Showing 16 changed files with 610 additions and 131 deletions.
21 changes: 11 additions & 10 deletions core/math/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,23 @@ class Geometry {
}

static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) {
#if 0
//do the function 'd' as defined by pb. I think is is dot product of some sort
#if 1
//do the function 'd' as defined by pb. I think is is dot product of some sort
#define d_of(m, n, o, p) ((m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z))

//calculate the parametric position on the 2 curves, mua and mub
real_t mua = ( d_of(p1,q1,q2,q1) * d_of(q2,q1,p2,p1) - d_of(p1,q1,p2,p1) * d_of(q2,q1,q2,q1) ) / ( d_of(p2,p1,p2,p1) * d_of(q2,q1,q2,q1) - d_of(q2,q1,p2,p1) * d_of(q2,q1,p2,p1) );
real_t mub = ( d_of(p1,q1,q2,q1) + mua * d_of(q2,q1,p2,p1) ) / d_of(q2,q1,q2,q1);
real_t mua = (d_of(p1, q1, q2, q1) * d_of(q2, q1, p2, p1) - d_of(p1, q1, p2, p1) * d_of(q2, q1, q2, q1)) / (d_of(p2, p1, p2, p1) * d_of(q2, q1, q2, q1) - d_of(q2, q1, p2, p1) * d_of(q2, q1, p2, p1));
real_t mub = (d_of(p1, q1, q2, q1) + mua * d_of(q2, q1, p2, p1)) / d_of(q2, q1, q2, q1);

//clip the value between [0..1] constraining the solution to lie on the original curves
if (mua < 0) mua = 0;
if (mub < 0) mub = 0;
if (mua > 1) mua = 1;
if (mub > 1) mub = 1;
c1 = p1.linear_interpolate(p2,mua);
c2 = q1.linear_interpolate(q2,mub);
#endif

c1 = p1.linear_interpolate(p2, mua);
c2 = q1.linear_interpolate(q2, mub);
#else
//this is broken do not use
Vector3 u = p2 - p1;
Vector3 v = q2 - q1;
Vector3 w = p1 - q1;
Expand All @@ -144,8 +144,9 @@ class Geometry {
c1 = w + sc * u;
c2 = w + tc * v;
// get the difference of the two closest points
//Vector dP = w + (sc * u) - (tc * v); // = L1(sc) - L2(tc)
// get the difference of the two closest points
//Vector dP = w + (sc * u) - (tc * v); // = L1(sc) - L2(tc)
#endif
}

static real_t get_closest_distance_between_segments(const Vector3 &p_from_a, const Vector3 &p_to_a, const Vector3 &p_from_b, const Vector3 &p_to_b) {
Expand Down
164 changes: 140 additions & 24 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1216,7 +1216,26 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
return rebind;
}

void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) {
struct RasterizerGLES3Particle {

float color[4];
float velocity_active[4];
float custom[4];
float xform_1[4];
float xform_2[4];
float xform_3[4];
};

struct RasterizerGLES3ParticleSort {

Vector3 z_dir;
bool operator()(const RasterizerGLES3Particle &p_a, const RasterizerGLES3Particle &p_b) const {

return z_dir.dot(Vector3(p_a.xform_1[3], p_a.xform_2[3], p_a.xform_3[3])) < z_dir.dot(Vector3(p_b.xform_1[3], p_b.xform_2[3], p_b.xform_3[3]));
}
};

void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transform &p_view_transform) {

switch (e->instance->base_type) {

Expand Down Expand Up @@ -1289,28 +1308,54 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) {
RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner);
RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry);

glBindVertexArray(s->instancing_array_id); // use the instancing array ID
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer
if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) {

glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing
RasterizerGLES3Particle *particle_array = (RasterizerGLES3Particle *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);

SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter;

if (particles->use_local_coords) {
sorter.compare.z_dir = e->instance->transform.affine_inverse().xform(p_view_transform.basis.get_axis(2)).normalized();
} else {
sorter.compare.z_dir = p_view_transform.basis.get_axis(2).normalized();
}

sorter.sort(particle_array, particles->amount);

glUnmapBuffer(GL_ARRAY_BUFFER);

glBindVertexArray(s->instancing_array_id); // use the instancing array ID
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer

} else {

glBindVertexArray(s->instancing_array_id); // use the instancing array ID
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer
}

int stride = sizeof(float) * 4 * 6;

//transform

glEnableVertexAttribArray(8); //xform x
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3);
glVertexAttribDivisor(8, 1);
glEnableVertexAttribArray(9); //xform y
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4);
glVertexAttribDivisor(9, 1);
glEnableVertexAttribArray(10); //xform z
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5);
glVertexAttribDivisor(10, 1);
glEnableVertexAttribArray(11); //color
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
glVertexAttribDivisor(11, 1);
glEnableVertexAttribArray(12); //custom
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2);
glVertexAttribDivisor(12, 1);
if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) {

glEnableVertexAttribArray(8); //xform x
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3);
glVertexAttribDivisor(8, 1);
glEnableVertexAttribArray(9); //xform y
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4);
glVertexAttribDivisor(9, 1);
glEnableVertexAttribArray(10); //xform z
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5);
glVertexAttribDivisor(10, 1);
glEnableVertexAttribArray(11); //color
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
glVertexAttribDivisor(11, 1);
glEnableVertexAttribArray(12); //custom
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2);
glVertexAttribDivisor(12, 1);
}

} break;
}
Expand Down Expand Up @@ -1491,17 +1536,88 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {

int amount = particles->amount;

if (s->index_array_len > 0) {
if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_LIFETIME) {
//split

int stride = sizeof(float) * 4 * 6;
int split = int(Math::ceil(particles->phase * particles->amount));

if (amount - split > 0) {
glEnableVertexAttribArray(8); //xform x
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 3);
glVertexAttribDivisor(8, 1);
glEnableVertexAttribArray(9); //xform y
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 4);
glVertexAttribDivisor(9, 1);
glEnableVertexAttribArray(10); //xform z
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 5);
glVertexAttribDivisor(10, 1);
glEnableVertexAttribArray(11); //color
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + 0);
glVertexAttribDivisor(11, 1);
glEnableVertexAttribArray(12); //custom
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 2);
glVertexAttribDivisor(12, 1);

glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
if (s->index_array_len > 0) {

storage->info.render_vertices_count += s->index_array_len * amount;
glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount - split);

storage->info.render_vertices_count += s->index_array_len * (amount - split);

} else {

glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount - split);

storage->info.render_vertices_count += s->array_len * (amount - split);
}
}

if (split > 0) {
glEnableVertexAttribArray(8); //xform x
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3);
glVertexAttribDivisor(8, 1);
glEnableVertexAttribArray(9); //xform y
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4);
glVertexAttribDivisor(9, 1);
glEnableVertexAttribArray(10); //xform z
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5);
glVertexAttribDivisor(10, 1);
glEnableVertexAttribArray(11); //color
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
glVertexAttribDivisor(11, 1);
glEnableVertexAttribArray(12); //custom
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2);
glVertexAttribDivisor(12, 1);

if (s->index_array_len > 0) {

glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, split);

storage->info.render_vertices_count += s->index_array_len * split;

} else {

glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, split);

storage->info.render_vertices_count += s->array_len * split;
}
}

} else {

glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);
if (s->index_array_len > 0) {

storage->info.render_vertices_count += s->array_len * amount;
glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);

storage->info.render_vertices_count += s->index_array_len * amount;

} else {

glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);

storage->info.render_vertices_count += s->array_len * amount;
}
}

} break;
Expand Down Expand Up @@ -1841,7 +1957,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_

if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry != e->geometry) {

_setup_geometry(e);
_setup_geometry(e, p_view_transform);
storage->info.render_surface_switch_count++;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ class RasterizerSceneGLES3 : public RasterizerScene {
_FORCE_INLINE_ void _set_cull(bool p_front, bool p_reverse_cull);

_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material *p_material, bool p_alpha_pass);
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *e, const Transform &p_view_transform);
_FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _setup_light(RenderList::Element *e, const Transform &p_view_transform);

Expand Down
Loading

3 comments on commit 4286aef

@Gibbz
Copy link

@Gibbz Gibbz commented on 4286aef Apr 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm playing with this now. I however see no particles in the editor.
Do you have a rough guide, just enough to get the particles to show in the editor?

@reduz
Copy link
Member Author

@reduz reduz commented on 4286aef Apr 9, 2017 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gibbz
Copy link

@Gibbz Gibbz commented on 4286aef Apr 9, 2017 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.