From e70d7294e243b0e3eafbd6279b8bb285aa2d2419 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Wed, 10 Mar 2021 10:54:21 +0000 Subject: [PATCH] Support ninepatch mode in GLES3 shader Although batching supported both ninepatch modes (fixed and scaling) when using ninepatch stretch mode, the ninepatch tiling modes (in GLES3) could only run through the shader. The shader only supported one of the ninepatch modes. This PR uses the hack method of #if defined in the shader to prevent the use of a conditional. The define is set at startup according to the project setting. --- drivers/gles3/rasterizer_canvas_gles3.cpp | 6 +++ drivers/gles3/shaders/canvas.glsl | 55 ++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index df0ab12a6ed..38fdb087869 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -2340,6 +2340,12 @@ void RasterizerCanvasGLES3::initialize() { glBindVertexArray(0); } // for vao + + // deal with ninepatch mode option + if (bdata.settings_ninepatch_mode == 1) { + state.canvas_shader.add_custom_define("#define USE_NINEPATCH_SCALING\n"); + } + gl_checkerror(); } diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 620968cd143..1e4e1c0d746 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -451,6 +451,47 @@ uniform bool np_draw_center; // left top right bottom in pixel coordinates uniform vec4 np_margins; +// there are two ninepatch modes, and we don't want to waste a conditional +#if defined USE_NINEPATCH_SCALING +float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, float s_ratio, int np_repeat, inout int draw_center) { + + float tex_size = 1.0 / tex_pixel_size; + + float screen_margin_begin = margin_begin / s_ratio; + float screen_margin_end = margin_end / s_ratio; + if (pixel < screen_margin_begin) { + return pixel * s_ratio * tex_pixel_size; + } else if (pixel >= draw_size - screen_margin_end) { + return (tex_size - (draw_size - pixel) * s_ratio) * tex_pixel_size; + } else { + if (!np_draw_center) { + draw_center--; + } + + if (np_repeat == 0) { //stretch + //convert to ratio + float ratio = (pixel - screen_margin_begin) / (draw_size - screen_margin_begin - screen_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 - screen_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 - screen_margin_begin - screen_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 - screen_margin_begin) / src_area; + ratio = mod(ratio * scale, 1.0); + return (margin_begin + ratio * dst_area) * tex_pixel_size; + } + } +} +#else 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; @@ -490,6 +531,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo } } } +#endif #endif #endif @@ -506,6 +548,17 @@ void main() { #ifdef USE_NINEPATCH int draw_center = 2; +#if defined USE_NINEPATCH_SCALING + float s_ratio = max((1.0 / color_texpixel_size.x) / abs(dst_rect.z), (1.0 / color_texpixel_size.y) / abs(dst_rect.w)); + s_ratio = max(1.0, s_ratio); + uv = vec2( + map_ninepatch_axis(pixel_size_interp.x, abs(dst_rect.z), color_texpixel_size.x, np_margins.x, np_margins.z, s_ratio, 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, s_ratio, np_repeat_v, draw_center)); + + if (draw_center == 0) { + color.a = 0.0; + } +#else 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)); @@ -513,7 +566,7 @@ void main() { if (draw_center == 0) { color.a = 0.0; } - +#endif uv = uv * src_rect.zw + src_rect.xy; //apply region if needed #endif