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.
This commit is contained in:
lawnjelly 2021-03-10 10:54:21 +00:00
parent 64a9e86c5c
commit e70d7294e2
2 changed files with 60 additions and 1 deletions

View file

@ -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();
}

View file

@ -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