Selaa lähdekoodia

Merge pull request #32170 from puthre/ninepatch-fix

GLES2 & GLES3 Fixes ninepatch margins for high resolution textures.
Rémi Verschelde 6 vuotta sitten
vanhempi
commit
a39aeade5b
2 muutettua tiedostoa jossa 39 lisäystä ja 27 poistoa
  1. 24 16
      drivers/gles2/rasterizer_canvas_gles2.cpp
  2. 15 11
      drivers/gles3/shaders/canvas.glsl

+ 24 - 16
drivers/gles2/rasterizer_canvas_gles2.cpp

@@ -761,6 +761,14 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 					source.size.y = tex->height;
 				}
 
+				float screen_scale = 1.0;
+
+				if (source.size.x != 0 && source.size.y != 0) {
+
+					screen_scale = MIN(np->rect.size.x / source.size.x, np->rect.size.y / source.size.y);
+					screen_scale = MIN(1.0, screen_scale);
+				}
+
 				// prepare vertex buffer
 
 				// this buffer contains [ POS POS UV UV ] *
@@ -777,13 +785,13 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 					buffer[(0 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
 					buffer[(0 * 4 * 4) + 3] = source.position.y * texpixel_size.y;
 
-					buffer[(0 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+					buffer[(0 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT] * screen_scale;
 					buffer[(0 * 4 * 4) + 5] = np->rect.position.y;
 
 					buffer[(0 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
 					buffer[(0 * 4 * 4) + 7] = source.position.y * texpixel_size.y;
 
-					buffer[(0 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+					buffer[(0 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT] * screen_scale;
 					buffer[(0 * 4 * 4) + 9] = np->rect.position.y;
 
 					buffer[(0 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
@@ -798,25 +806,25 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 					// second row
 
 					buffer[(1 * 4 * 4) + 0] = np->rect.position.x;
-					buffer[(1 * 4 * 4) + 1] = np->rect.position.y + np->margin[MARGIN_TOP];
+					buffer[(1 * 4 * 4) + 1] = np->rect.position.y + np->margin[MARGIN_TOP] * screen_scale;
 
 					buffer[(1 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
 					buffer[(1 * 4 * 4) + 3] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
 
-					buffer[(1 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
-					buffer[(1 * 4 * 4) + 5] = np->rect.position.y + np->margin[MARGIN_TOP];
+					buffer[(1 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT] * screen_scale;
+					buffer[(1 * 4 * 4) + 5] = np->rect.position.y + np->margin[MARGIN_TOP] * screen_scale;
 
 					buffer[(1 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
 					buffer[(1 * 4 * 4) + 7] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
 
-					buffer[(1 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
-					buffer[(1 * 4 * 4) + 9] = np->rect.position.y + np->margin[MARGIN_TOP];
+					buffer[(1 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT] * screen_scale;
+					buffer[(1 * 4 * 4) + 9] = np->rect.position.y + np->margin[MARGIN_TOP] * screen_scale;
 
 					buffer[(1 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
 					buffer[(1 * 4 * 4) + 11] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
 
 					buffer[(1 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
-					buffer[(1 * 4 * 4) + 13] = np->rect.position.y + np->margin[MARGIN_TOP];
+					buffer[(1 * 4 * 4) + 13] = np->rect.position.y + np->margin[MARGIN_TOP] * screen_scale;
 
 					buffer[(1 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
 					buffer[(1 * 4 * 4) + 15] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
@@ -824,25 +832,25 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 					// third row
 
 					buffer[(2 * 4 * 4) + 0] = np->rect.position.x;
-					buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
+					buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM] * screen_scale;
 
 					buffer[(2 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
 					buffer[(2 * 4 * 4) + 3] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
 
-					buffer[(2 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
-					buffer[(2 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
+					buffer[(2 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT] * screen_scale;
+					buffer[(2 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM] * screen_scale;
 
 					buffer[(2 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
 					buffer[(2 * 4 * 4) + 7] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
 
-					buffer[(2 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
-					buffer[(2 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
+					buffer[(2 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT] * screen_scale;
+					buffer[(2 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM] * screen_scale;
 
 					buffer[(2 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
 					buffer[(2 * 4 * 4) + 11] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
 
 					buffer[(2 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
-					buffer[(2 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
+					buffer[(2 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM] * screen_scale;
 
 					buffer[(2 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
 					buffer[(2 * 4 * 4) + 15] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
@@ -855,13 +863,13 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 					buffer[(3 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
 					buffer[(3 * 4 * 4) + 3] = (source.position.y + source.size.y) * texpixel_size.y;
 
-					buffer[(3 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+					buffer[(3 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT] * screen_scale;
 					buffer[(3 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y;
 
 					buffer[(3 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
 					buffer[(3 * 4 * 4) + 7] = (source.position.y + source.size.y) * texpixel_size.y;
 
-					buffer[(3 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+					buffer[(3 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT] * screen_scale;
 					buffer[(3 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y;
 
 					buffer[(3 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;

+ 15 - 11
drivers/gles3/shaders/canvas.glsl

@@ -380,14 +380,16 @@ 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 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;
 
-	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;
+	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--;
@@ -395,22 +397,22 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
 
 		if (np_repeat == 0) { //stretch
 			//convert to ratio
-			float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end);
+			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 - margin_begin), tex_size - margin_begin - margin_end);
+			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 - margin_begin - margin_end;
+			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 - margin_begin) / src_area;
+			float ratio = (pixel - screen_margin_begin) / src_area;
 			ratio = mod(ratio * scale, 1.0);
 			return (margin_begin + ratio * dst_area) * tex_pixel_size;
 		}
@@ -432,9 +434,11 @@ void main() {
 #ifdef USE_NINEPATCH
 
 	int draw_center = 2;
+	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, 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));
+			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;