diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 89 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.h | 3 | ||||
| -rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 82 |
3 files changed, 112 insertions, 62 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 5d7929b9de..c71bf22965 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -165,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(); @@ -179,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() { @@ -187,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) { @@ -259,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) { @@ -273,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); @@ -280,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) { @@ -494,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)) - - //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); + Size2 texpixel_size; - //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; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 76e0fbd48f..5f435275df 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -67,6 +67,7 @@ public: CanvasShadowShaderGLES3 canvas_shadow_shader; bool using_texture_rect; + bool using_ninepatch; RID current_tex; RID current_normal; @@ -111,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/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 00744d8dc2..e97ce62daa 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -45,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 @@ -142,6 +148,12 @@ 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; @@ -277,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; @@ -287,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; @@ -309,6 +389,8 @@ void main() { #endif + + vec3 normal; #if defined(NORMAL_USED) |