From 31fb54742b4b8e08716813f7de9bd8379ea30aaf Mon Sep 17 00:00:00 2001 From: johan Date: Wed, 18 Mar 2020 02:05:23 -0400 Subject: [PATCH] Editor 2D: Change pixel alignment strategy, fix jittering in high zoom Alignment of scene pixels on screen pixel ensure a crisp rendering of small features (such as text). Unfortunately, alignment of top left pixel on screen adds a lot of jittering when zooming at high zoom factor. This change allow to snap the top left scene pixel on the closest screen pixel (not only the top-left most), and we do so only when the scale factor is an integer. (cherry picked from commit 1c02906a6fa7ca1224345fe3ae19ab9879165a0a) --- editor/plugins/canvas_item_editor_plugin.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 879de58bbce..6ce7f72e456 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4217,10 +4217,20 @@ void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) { float prev_zoom = zoom; zoom = p_zoom; - Point2 ofs = p_position; - ofs = ofs / prev_zoom - ofs / zoom; - view_offset.x = Math::round(view_offset.x + ofs.x); - view_offset.y = Math::round(view_offset.y + ofs.y); + + view_offset += p_position / prev_zoom - p_position / zoom; + + // We want to align in-scene pixels to screen pixels, this prevents blurry rendering + // in small details (texts, lines). + // This correction adds a jitter movement when zooming, so we correct only when the + // zoom factor is an integer. (in the other cases, all pixels won't be aligned anyway) + float closest_zoom_factor = Math::round(zoom); + if (Math::is_zero_approx(zoom - closest_zoom_factor)) { + // make sure scene pixel at view_offset is aligned on a screen pixel + Vector2 view_offset_int = view_offset.floor(); + Vector2 view_offset_frac = view_offset - view_offset_int; + view_offset = view_offset_int + (view_offset_frac * closest_zoom_factor).round() / closest_zoom_factor; + } _update_zoom_label(); update_viewport();