Browse Source

Merge pull request #92997 from Calinou/styleboxflat-antialiasing-adjust-for-stretch-scale

Adjust StyleBoxFlat antialiasing to account for 2D stretch scale
Thaddeus Crews 7 months ago
parent
commit
3d523ee86d
2 changed files with 30 additions and 9 deletions
  1. 1 1
      doc/classes/Viewport.xml
  2. 29 8
      scene/resources/style_box_flat.cpp

+ 1 - 1
doc/classes/Viewport.xml

@@ -108,7 +108,7 @@
 			<return type="Transform2D" />
 			<description>
 				Returns the automatically computed 2D stretch transform, taking the [Viewport]'s stretch settings into account. The final value is multiplied by [member Window.content_scale_factor], but only for the root viewport. If this method is called on a [SubViewport] (e.g., in a scene tree with [SubViewportContainer] and [SubViewport]), the scale factor of the root window will not be applied. Using [method Transform2D.get_scale] on the returned value, this can be used to compensate for scaling when zooming a [Camera2D] node, or to scale down a [TextureRect] to be pixel-perfect regardless of the automatically computed scale factor.
-				[b]Note:[/b] Due to how pixel scaling works, the transform's X scale value may differ slightly from the Y scale, even when [member Window.content_scale_aspect] is set to a mode that preserves pixel aspect ratio. If [member Window.content_scale_aspect] is [constant Window.CONTENT_SCALE_ASPECT_IGNORE], the X value may differ [i]significantly[/i] from Y due to differences between the original aspect ratio and the window aspect ratio.
+				[b]Note:[/b] Due to how pixel scaling works, the returned transform's X and Y scale may differ slightly, even when [member Window.content_scale_aspect] is set to a mode that preserves the pixels' aspect ratio. If [member Window.content_scale_aspect] is [constant Window.CONTENT_SCALE_ASPECT_IGNORE], the X and Y scale may differ [i]significantly[/i].
 			</description>
 		</method>
 		<method name="get_texture" qualifiers="const">

+ 29 - 8
scene/resources/style_box_flat.cpp

@@ -30,6 +30,8 @@
 
 #include "style_box_flat.h"
 
+#include "scene/main/scene_tree.h"
+#include "scene/main/window.h"
 #include "servers/rendering_server.h"
 
 float StyleBoxFlat::get_style_margin(Side p_side) const {
@@ -408,10 +410,28 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
 	Rect2 infill_rect = style_rect.grow_individual(-adapted_border[SIDE_LEFT], -adapted_border[SIDE_TOP], -adapted_border[SIDE_RIGHT], -adapted_border[SIDE_BOTTOM]);
 
 	Rect2 border_style_rect = style_rect;
+
+	real_t aa_size_scaled = 1.0f;
+	if (aa_on) {
+		real_t scale_factor = 1.0f;
+		const SceneTree *tree = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());
+		if (tree) {
+			const Window *window = tree->get_root();
+			const Vector2 stretch_scale = window->get_stretch_transform().get_scale();
+			scale_factor = MIN(stretch_scale.x, stretch_scale.y);
+		}
+
+		// Adjust AA feather size to account for the 2D scale factor, so that
+		// antialiasing doesn't become blurry at viewport resolutions higher
+		// than the default when using the `canvas_items` stretch mode
+		// (or when using `content_scale_factor` values different than `1.0`).
+		aa_size_scaled = aa_size / scale_factor;
+	}
+
 	if (aa_on) {
 		for (int i = 0; i < 4; i++) {
 			if (border_width[i] > 0) {
-				border_style_rect = border_style_rect.grow_side((Side)i, -aa_size);
+				border_style_rect = border_style_rect.grow_side((Side)i, -aa_size_scaled);
 			}
 		}
 	}
@@ -457,26 +477,27 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
 		real_t aa_border_width_half[4];
 		real_t aa_fill_width[4];
 		real_t aa_fill_width_half[4];
+
 		if (draw_border) {
 			for (int i = 0; i < 4; i++) {
 				if (border_width[i] > 0) {
-					aa_border_width[i] = aa_size;
-					aa_border_width_half[i] = aa_size / 2;
+					aa_border_width[i] = aa_size_scaled;
+					aa_border_width_half[i] = aa_size_scaled * 0.5;
 					aa_fill_width[i] = 0;
 					aa_fill_width_half[i] = 0;
 				} else {
 					aa_border_width[i] = 0;
 					aa_border_width_half[i] = 0;
-					aa_fill_width[i] = aa_size;
-					aa_fill_width_half[i] = aa_size / 2;
+					aa_fill_width[i] = aa_size_scaled;
+					aa_fill_width_half[i] = aa_size_scaled * 0.5;
 				}
 			}
 		} else {
 			for (int i = 0; i < 4; i++) {
 				aa_border_width[i] = 0;
 				aa_border_width_half[i] = 0;
-				aa_fill_width[i] = aa_size;
-				aa_fill_width_half[i] = aa_size / 2;
+				aa_fill_width[i] = aa_size_scaled;
+				aa_fill_width_half[i] = aa_size_scaled * 0.5;
 			}
 		}
 
@@ -529,7 +550,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
 	}
 
 	// Compute UV coordinates.
-	Rect2 uv_rect = style_rect.grow(aa_on ? aa_size : 0);
+	Rect2 uv_rect = style_rect.grow(aa_on ? aa_size_scaled : 0);
 	uvs.resize(verts.size());
 	Point2 *uvs_ptr = uvs.ptrw();
 	for (int i = 0; i < verts.size(); i++) {