diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-06-21 16:25:45 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-06-21 16:26:26 -0300 |
commit | 95560e02c5eed3561996ed2b1d1e47e26e8bb81c (patch) | |
tree | 8e53927435484e10e444e6e2f745b2ddc19029e6 /drivers | |
parent | 3c1fd26bb0c2e97b927343e5488aa6d646e2e27c (diff) |
2D GPU Particles working..
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 163 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.h | 4 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 3 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.cpp | 2 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 44 |
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 |