summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2017-06-21 16:25:45 -0300
committerJuan Linietsky <reduzio@gmail.com>2017-06-21 16:26:26 -0300
commit95560e02c5eed3561996ed2b1d1e47e26e8bb81c (patch)
tree8e53927435484e10e444e6e2f745b2ddc19029e6 /drivers
parent3c1fd26bb0c2e97b927343e5488aa6d646e2e27c (diff)
2D GPU Particles working..
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp163
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h4
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp3
-rw-r--r--drivers/gles3/shader_gles3.cpp2
-rw-r--r--drivers/gles3/shaders/canvas.glsl44
5 files changed, 215 insertions, 1 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index a8895f7bfc..5d7929b9de 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "rasterizer_canvas_gles3.h"
+#include "servers/visual/visual_server_raster.h"
#include "global_config.h"
#include "os/os.h"
@@ -608,6 +609,133 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
_draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
} break;
+ case Item::Command::TYPE_PARTICLES: {
+
+ Item::CommandParticles *particles_cmd = static_cast<Item::CommandParticles *>(c);
+
+ RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles);
+ if (!particles)
+ break;
+
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white
+
+ VisualServerRaster::redraw_request();
+
+ storage->particles_request_process(particles_cmd->particles);
+ //enable instancing
+
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true);
+ //reset shader and force rebind
+ state.using_texture_rect = true;
+ _set_texture_rect_mode(false);
+
+ RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map);
+
+ if (texture) {
+ Size2 texpixel_size(1.0 / (texture->width / particles_cmd->h_frames), 1.0 / (texture->height / particles_cmd->v_frames));
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
+ } else {
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0));
+ }
+
+ if (!particles->use_local_coords) {
+
+ Transform2D inv_xf;
+ inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y));
+ inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y));
+ inv_xf.set_origin(Vector2(particles->emission_transform.get_origin().x, particles->emission_transform.get_origin().y));
+ inv_xf.affine_invert();
+
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf);
+ }
+
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::H_FRAMES, particles_cmd->h_frames);
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::V_FRAMES, particles_cmd->v_frames);
+
+ glBindVertexArray(data.particle_quad_array); //use particle quad array
+ glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer
+
+ int stride = sizeof(float) * 4 * 6;
+
+ int amount = particles->amount;
+
+ 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);
+
+ glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount);
+ } else {
+ //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);
+
+ glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, 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);
+
+ glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split);
+ }
+ }
+
+ glBindVertexArray(0);
+
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false);
+ state.using_texture_rect = true;
+ _set_texture_rect_mode(false);
+
+ } break;
case Item::Command::TYPE_CIRCLE: {
_set_texture_rect_mode(false);
@@ -1351,7 +1479,39 @@ void RasterizerCanvasGLES3::initialize() {
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
}
+ {
+ //particle quad buffers
+
+ glGenBuffers(1, &data.particle_quad_vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, data.particle_quad_vertices);
+ {
+ //quad of size 1, with pivot on the center for particles, then regular UVS. Color is general plus fetched from particle
+ const float qv[16] = {
+ -0.5, -0.5,
+ 0.0, 0.0,
+ -0.5, 0.5,
+ 0.0, 1.0,
+ 0.5, 0.5,
+ 1.0, 1.0,
+ 0.5, -0.5,
+ 1.0, 0.0
+ };
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+
+ glGenVertexArrays(1, &data.particle_quad_array);
+ glBindVertexArray(data.particle_quad_array);
+ glBindBuffer(GL_ARRAY_BUFFER, data.particle_quad_vertices);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (float *)0 + 2);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+ }
{
uint32_t poly_size = GLOBAL_DEF("rendering/buffers/canvas_polygon_buffer_size_kb", 128);
@@ -1428,6 +1588,9 @@ void RasterizerCanvasGLES3::finalize() {
glDeleteBuffers(1, &data.canvas_quad_vertices);
glDeleteVertexArrays(1, &data.canvas_quad_array);
+ glDeleteBuffers(1, &data.canvas_quad_vertices);
+ glDeleteVertexArrays(1, &data.canvas_quad_array);
+
glDeleteVertexArrays(1, &data.polygon_buffer_pointer_array);
}
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 4996f0a6b2..76e0fbd48f 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -51,6 +51,10 @@ public:
GLuint polygon_buffer_quad_arrays[4];
GLuint polygon_buffer_pointer_array;
GLuint polygon_index_buffer;
+
+ GLuint particle_quad_vertices;
+ GLuint particle_quad_array;
+
uint32_t polygon_buffer_size;
} data;
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 85331342e9..81baf542c0 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -2326,6 +2326,9 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
if (E->get().order < 0)
continue; // texture, does not go here
+ //if (material->shader->mode == VS::SHADER_PARTICLES) {
+ // print_line("uniform " + String(E->key()) + " order " + itos(E->get().order) + " offset " + itos(material->shader->ubo_offsets[E->get().order]));
+ //}
//regular uniform
uint8_t *data = &local_ubo[material->shader->ubo_offsets[E->get().order]];
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 8c6d15c3b7..e08ef0ad12 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -361,6 +361,8 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
ERR_FAIL_V(NULL);
}
+ //_display_error_with_code("pepo", strings);
+
/* FRAGMENT SHADER */
strings.resize(strings_base_size);
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 7be6ee857a..00744d8dc2 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -11,11 +11,26 @@ uniform vec4 src_rect;
#else
+#ifdef USE_INSTANCING
+
+layout(location=8) in highp vec4 instance_xform0;
+layout(location=9) in highp vec4 instance_xform1;
+layout(location=10) in highp vec4 instance_xform2;
+layout(location=11) in lowp vec4 instance_color;
+
+#ifdef USE_INSTANCE_CUSTOM
+layout(location=12) in highp vec4 instance_custom_data;
+#endif
+
+#endif
+
layout(location=4) in highp vec2 uv_attrib;
//skeletn
#endif
+uniform highp vec2 color_texpixel_size;
+
layout(std140) uniform CanvasItemData { //ubo:0
@@ -64,7 +79,10 @@ const bool at_light_pass = true;
const bool at_light_pass = false;
#endif
-
+#ifdef USE_PARTICLES
+uniform int h_frames;
+uniform int v_frames;
+#endif
VERTEX_SHADER_GLOBALS
@@ -82,6 +100,12 @@ void main() {
vec4 vertex_color = color_attrib;
+#ifdef USE_INSTANCING
+ mat4 extra_matrix2 = extra_matrix * transpose(mat4(instance_xform0,instance_xform1,instance_xform2,vec4(0.0,0.0,0.0,1.0)));
+ vertex_color*=instance_color;
+#else
+ mat4 extra_matrix2 = extra_matrix;
+#endif
#ifdef USE_TEXTURE_RECT
@@ -95,6 +119,22 @@ void main() {
#endif
+#ifdef USE_PARTICLES
+ //scale by texture size
+ outvec.xy/=color_texpixel_size;
+
+ //compute h and v frames and adjust UV interp for animation
+ int total_frames = h_frames * v_frames;
+ int frame = min(int(float(total_frames) *instance_custom_data.z),total_frames-1);
+ float frame_w = 1.0/float(h_frames);
+ float frame_h = 1.0/float(v_frames);
+ uv_interp.x = uv_interp.x * frame_w + frame_w * float(frame % h_frames);
+ uv_interp.y = uv_interp.y * frame_h + frame_h * float(frame / v_frames);
+
+#endif
+
+#define extra_matrix extra_matrix2
+
{
vec2 src_vtx=outvec.xy;
@@ -107,6 +147,8 @@ VERTEX_SHADER_CODE
outvec = modelview_matrix * outvec;
#endif
+#undef extra_matrix
+
color_interp = vertex_color;
#ifdef USE_PIXEL_SNAP