diff options
Diffstat (limited to 'drivers/gles3')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 252 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.h | 7 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 62 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 5 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 33 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 6 | ||||
-rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 1 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.cpp | 2 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 126 | ||||
-rw-r--r-- | drivers/gles3/shaders/copy.glsl | 5 | ||||
-rw-r--r-- | drivers/gles3/shaders/particles.glsl | 9 |
11 files changed, 440 insertions, 68 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index a8895f7bfc..c71bf22965 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" @@ -164,6 +165,7 @@ void RasterizerCanvasGLES3::canvas_begin() { state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, false); state.canvas_shader.set_custom_shader(0); state.canvas_shader.bind(); @@ -178,6 +180,7 @@ void RasterizerCanvasGLES3::canvas_begin() { glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_item_ubo); glBindVertexArray(data.canvas_quad_array); state.using_texture_rect = true; + state.using_ninepatch = false; } void RasterizerCanvasGLES3::canvas_end() { @@ -186,6 +189,7 @@ void RasterizerCanvasGLES3::canvas_end() { glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0); state.using_texture_rect = false; + state.using_ninepatch = false; } RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { @@ -258,9 +262,9 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con return tex_return; } -void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable) { +void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepatch) { - if (state.using_texture_rect == p_enable) + if (state.using_texture_rect == p_enable && state.using_ninepatch == p_ninepatch) return; if (p_enable) { @@ -272,6 +276,7 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, p_ninepatch && p_enable); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT, p_enable); state.canvas_shader.bind(); state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); @@ -279,6 +284,7 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable) { state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); state.using_texture_rect = p_enable; + state.using_ninepatch = p_ninepatch; } void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { @@ -493,79 +499,41 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur Item::CommandNinePatch *np = static_cast<Item::CommandNinePatch *>(c); - _set_texture_rect_mode(true); + _set_texture_rect_mode(true, true); glVertexAttrib4f(VS::ARRAY_COLOR, np->color.r, np->color.g, np->color.b, np->color.a); RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(np->texture, np->normal_map); - if (!texture) { - - glVertexAttrib4f(1, np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); - glVertexAttrib4f(2, 0, 0, 1, 1); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - continue; - } - - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); - -#define DSTRECT(m_x, m_y, m_w, m_h) state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(m_x, m_y, m_w, m_h)) -#define SRCRECT(m_x, m_y, m_w, m_h) state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color((m_x)*texpixel_size.x, (m_y)*texpixel_size.y, (m_w)*texpixel_size.x, (m_h)*texpixel_size.y)) + Size2 texpixel_size; - //top left - DSTRECT(np->rect.position.x, np->rect.position.y, np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); - SRCRECT(np->source.position.x, np->source.position.y, np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - //top right - DSTRECT(np->rect.position.x + np->rect.size.width - np->margin[MARGIN_RIGHT], np->rect.position.y, np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - SRCRECT(np->source.position.x + np->source.size.width - np->margin[MARGIN_RIGHT], np->source.position.y, np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + if (!texture) { - //bottom right - DSTRECT(np->rect.position.x + np->rect.size.width - np->margin[MARGIN_RIGHT], np->rect.position.y + np->rect.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]); - SRCRECT(np->source.position.x + np->source.size.width - np->margin[MARGIN_RIGHT], np->source.position.y + np->source.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + texpixel_size = Size2(1, 1); - //bottom left - DSTRECT(np->rect.position.x, np->rect.position.y + np->rect.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_LEFT], np->margin[MARGIN_BOTTOM]); - SRCRECT(np->source.position.x, np->source.position.y + np->source.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_LEFT], np->margin[MARGIN_BOTTOM]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1)); - //top - DSTRECT(np->rect.position.x + np->margin[MARGIN_LEFT], np->rect.position.y, np->rect.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - SRCRECT(np->source.position.x + np->margin[MARGIN_LEFT], np->source.position.y, np->source.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } else { - //bottom - DSTRECT(np->rect.position.x + np->margin[MARGIN_LEFT], np->rect.position.y + np->rect.size.height - np->margin[MARGIN_BOTTOM], np->rect.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - SRCRECT(np->source.position.x + np->margin[MARGIN_LEFT], np->source.position.y + np->source.size.height - np->margin[MARGIN_BOTTOM], np->source.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + if (np->source != Rect2()) { + texpixel_size = Size2(1.0 / np->source.size.width, 1.0 / np->source.size.height); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(np->source.position.x / texture->width, np->source.position.y / texture->height, np->source.size.x / texture->width, np->source.size.y / texture->height)); + } else { + texpixel_size = Size2(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1)); + } + } - //left - DSTRECT(np->rect.position.x, np->rect.position.y + np->margin[MARGIN_TOP], np->margin[MARGIN_LEFT], np->rect.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - SRCRECT(np->source.position.x, np->source.position.y + np->margin[MARGIN_TOP], np->margin[MARGIN_LEFT], np->source.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); + state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_REPEAT_H, int(np->axis_x)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_REPEAT_V, int(np->axis_y)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_DRAW_CENTER, np->draw_center); + state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_MARGINS, Color(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM])); + state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y)); - //right - DSTRECT(np->rect.position.x + np->rect.size.width - np->margin[MARGIN_RIGHT], np->rect.position.y + np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], np->rect.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - SRCRECT(np->source.position.x + np->source.size.width - np->margin[MARGIN_RIGHT], np->source.position.y + np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], np->source.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - if (np->draw_center) { - - //center - DSTRECT(np->rect.position.x + np->margin[MARGIN_LEFT], np->rect.position.y + np->margin[MARGIN_TOP], np->rect.size.x - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->rect.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - SRCRECT(np->source.position.x + np->margin[MARGIN_LEFT], np->source.position.y + np->margin[MARGIN_TOP], np->source.size.x - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->source.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - -#undef SRCRECT -#undef DSTRECT - storage->frame.canvas_draw_commands++; } break; @@ -608,6 +576,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 +1446,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 +1555,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..5f435275df 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; @@ -63,6 +67,7 @@ public: CanvasShadowShaderGLES3 canvas_shadow_shader; bool using_texture_rect; + bool using_ninepatch; RID current_tex; RID current_normal; @@ -107,7 +112,7 @@ public: virtual void canvas_begin(); virtual void canvas_end(); - _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable); + _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false); _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 913aa62452..96c3da99f0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -977,6 +977,27 @@ void RasterizerSceneGLES3::environment_set_fog_height(RID p_env, bool p_enable, env->fog_height_curve = p_height_curve; } +bool RasterizerSceneGLES3::is_environment(RID p_env) { + + return environment_owner.owns(p_env); +} + +VS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) { + + const Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); + + return env->bg_mode; +} + +int RasterizerSceneGLES3::environment_get_canvas_max_layer(RID p_env) { + + const Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, -1); + + return env->canvas_max_layer; +} + RID RasterizerSceneGLES3::light_instance_create(RID p_light) { LightInstance *light_instance = memnew(LightInstance); @@ -3561,7 +3582,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE), 1, ss); glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE), 1, ds); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse); + glBindTexture(GL_TEXTURE_2D, composite_from); glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[0].fbo); glViewport(0, 0, exposure_shrink_size, exposure_shrink_size); @@ -3957,6 +3978,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; use_mrt = use_mrt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW; + use_mrt = use_mrt && env && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS); glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); @@ -4020,6 +4042,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->frame.clear_request = false; } + } else if (env->bg_mode == VS::ENV_BG_CANVAS) { + + clear_color = env->bg_color.to_linear(); + storage->frame.clear_request = false; } else if (env->bg_mode == VS::ENV_BG_COLOR) { clear_color = env->bg_color.to_linear(); @@ -4037,7 +4063,39 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->frame.clear_request = false; } - glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular + if (!env || env->bg_mode != VS::ENV_BG_KEEP) { + glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular + } + + if (env && env->bg_mode == VS::ENV_BG_CANVAS) { + //copy canvas to 3d buffer and convert it to linear + + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true); + + storage->shaders.copy.bind(); + + _copy_screen(); + + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); + + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } state.texscreen_copied = false; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 3e15da52ab..c52a00bf17 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -536,6 +536,11 @@ public: virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve); virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve); + virtual bool is_environment(RID p_env); + + virtual VS::EnvironmentBG environment_get_background(RID p_env); + virtual int environment_get_canvas_max_layer(RID p_env); + /* LIGHT INSTANCE */ struct LightDataUBO { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 85331342e9..f7e1fdee9d 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]]; @@ -5285,6 +5288,7 @@ void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_de if (particles->clear) { particles->cycle_number = 0; + particles->random_seed = Math::rand(); } else if (new_phase < particles->phase) { particles->cycle_number++; } @@ -5295,6 +5299,8 @@ void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_de shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta * particles->speed_scale); shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, particles->clear); + glUniform1ui(shaders.particles.get_uniform_location(ParticlesShaderGLES3::RANDOM_SEED), particles->random_seed); + if (particles->use_local_coords) shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform()); else @@ -5350,6 +5356,33 @@ void RasterizerStorageGLES3::update_particles() { Particles *particles = particle_update_list.first()->self(); + if (particles->inactive && !particles->emitting) { + + particle_update_list.remove(particle_update_list.first()); + continue; + } + + if (particles->emitting) { + if (particles->inactive) { + //restart system from scratch + particles->prev_ticks = 0; + particles->phase = 0; + particles->prev_phase = 0; + particles->clear = true; + particles->particle_valid_histories[0] = false; + particles->particle_valid_histories[1] = false; + } + particles->inactive = false; + particles->inactive_time = 0; + } else { + particles->inactive_time += particles->speed_scale * frame.delta; + if (particles->inactive_time > particles->lifetime * 1.2) { + particles->inactive = true; + particle_update_list.remove(particle_update_list.first()); + continue; + } + } + Material *material = material_owner.getornull(particles->process_material); if (!material || !material->shader || material->shader->mode != VS::SHADER_PARTICLES) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index ca0194bd5e..65026a16ec 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -1033,6 +1033,8 @@ public: struct Particles : public GeometryOwner { + bool inactive; + float inactive_time; bool emitting; int amount; float lifetime; @@ -1060,6 +1062,7 @@ public: float phase; float prev_phase; uint64_t prev_ticks; + uint32_t random_seed; uint32_t cycle_number; @@ -1088,6 +1091,7 @@ public: frame_remainder = 0; histories_enabled = false; speed_scale = 1.0; + random_seed = 0; custom_aabb = Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8)); @@ -1098,6 +1102,8 @@ public: prev_ticks = 0; clear = true; + inactive = true; + inactive_time = false; glGenBuffers(2, particle_buffers); glGenVertexArrays(2, particle_vaos); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 3376f99112..41421a3e2f 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -795,6 +795,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index"; actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; + actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; 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..e97ce62daa 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 @@ -30,6 +45,12 @@ uniform highp mat4 extra_matrix; out mediump vec2 uv_interp; out mediump vec4 color_interp; +#ifdef USE_NINEPATCH + +out highp vec2 pixel_size_interp; +#endif + + #ifdef USE_LIGHTING layout(std140) uniform LightData { //ubo:1 @@ -64,7 +85,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 +106,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 +125,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; @@ -102,11 +148,19 @@ VERTEX_SHADER_CODE } + +#ifdef USE_NINEPATCH + + pixel_size_interp=abs(dst_rect.zw) * vertex; +#endif + #if !defined(SKIP_TRANSFORM_USED) outvec = extra_matrix * outvec; outvec = modelview_matrix * outvec; #endif +#undef extra_matrix + color_interp = vertex_color; #ifdef USE_PIXEL_SNAP @@ -235,6 +289,58 @@ uniform vec4 dst_rect; uniform vec4 src_rect; uniform bool clip_rect_uv; +#ifdef USE_NINEPATCH + +in highp vec2 pixel_size_interp; + +uniform int np_repeat_v; +uniform int np_repeat_h; +uniform bool np_draw_center; +//left top right bottom in pixel coordinates +uniform vec4 np_margins; + + + +float map_ninepatch_axis(float pixel, float draw_size,float tex_pixel_size,float margin_begin,float margin_end,int np_repeat,inout int draw_center) { + + + float tex_size = 1.0/tex_pixel_size; + + if (pixel < margin_begin) { + return pixel * tex_pixel_size; + } else if (pixel >= draw_size-margin_end) { + return (tex_size-(draw_size-pixel)) * tex_pixel_size; + } else { + if (!np_draw_center){ + draw_center--; + } + + if (np_repeat==0) { //stretch + //convert to ratio + float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end); + //scale to source texture + return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size; + } else if (np_repeat==1) { //tile + //convert to ratio + float ofs = mod((pixel - margin_begin), tex_size - margin_begin - margin_end); + //scale to source texture + return (margin_begin + ofs) * tex_pixel_size; + } else if (np_repeat==2) { //tile fit + //convert to ratio + float src_area = draw_size - margin_begin - margin_end; + float dst_area = tex_size - margin_begin - margin_end; + float scale = max(1.0,floor(src_area / max(dst_area,0.0000001) + 0.5)); + + //convert to ratio + float ratio = (pixel - margin_begin) / src_area; + ratio = mod(ratio * scale,1.0); + return (margin_begin + ratio * dst_area) * tex_pixel_size; + } + } + +} + +#endif #endif uniform bool use_default_normal; @@ -245,6 +351,22 @@ void main() { vec2 uv = uv_interp; #ifdef USE_TEXTURE_RECT + +#ifdef USE_NINEPATCH + + int draw_center=2; + uv = vec2( + map_ninepatch_axis(pixel_size_interp.x,abs(dst_rect.z),color_texpixel_size.x,np_margins.x,np_margins.z,np_repeat_h,draw_center), + map_ninepatch_axis(pixel_size_interp.y,abs(dst_rect.w),color_texpixel_size.y,np_margins.y,np_margins.w,np_repeat_v,draw_center) + ); + + if (draw_center==0) { + color.a=0; + } + + uv = uv*src_rect.zw+src_rect.xy; //apply region if needed +#endif + if (clip_rect_uv) { vec2 half_texpixel = color_texpixel_size * 0.5; @@ -267,6 +389,8 @@ void main() { #endif + + vec3 normal; #if defined(NORMAL_USED) diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 4c8648903e..b0fb525e20 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -129,6 +129,11 @@ void main() { color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308))); #endif +#ifdef SRGB_TO_LINEAR + + color.rgb = mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1 + 0.055)),vec3(2.4)),color.rgb * (1.0 / 12.92),lessThan(color.rgb,vec3(0.04045))); +#endif + #ifdef DEBUG_GRADIENT color.rg=uv_interp; color.b=0.0; diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index 7e7b083f73..ec2577538c 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -37,6 +37,7 @@ uniform bool clear; uniform uint cycle; uniform float lifetime; uniform mat4 emission_transform; +uniform uint random_seed; out highp vec4 out_color; //tfb: @@ -104,7 +105,9 @@ void main() { bool shader_active = velocity_active.a > 0.5; if (system_phase > prev_system_phase) { - if (prev_system_phase < restart_phase && system_phase >= restart_phase) { + // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed + + if (restart_phase >= prev_system_phase && restart_phase < system_phase ) { restart=true; #ifdef USE_FRACTIONAL_DELTA local_delta = (system_phase - restart_phase) * lifetime; @@ -112,12 +115,12 @@ void main() { } } else { - if (prev_system_phase < restart_phase) { + if (restart_phase >= prev_system_phase) { restart=true; #ifdef USE_FRACTIONAL_DELTA local_delta = (1.0 - restart_phase + system_phase) * lifetime; #endif - } else if (system_phase >= restart_phase) { + } else if (restart_phase < system_phase ) { restart=true; #ifdef USE_FRACTIONAL_DELTA local_delta = (system_phase - restart_phase) * lifetime; |