From ab76cd6ff27a503a50cf1fbb2b434321971abddc Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Fri, 29 Oct 2021 12:14:51 +0100 Subject: [PATCH] Faster editor line drawing - Path2D and draw_line Changes the Path2D drawing to use POLYLINE instead of thick lines. Add a path to translate thick lines (that are not using anti-aliasing) to draw as polygons instead. This should be faster because polygons can be batched. --- scene/2d/path_2d.cpp | 14 ++++---- scene/2d/path_2d.h | 1 + servers/visual/visual_server_canvas.cpp | 43 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 9c7b2626d4..6d3113fbe0 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -101,16 +101,18 @@ void Path2D::_notification(int p_what) { #endif const Color color = Color(1.0, 1.0, 1.0, 1.0); - for (int i = 0; i < curve->get_point_count(); i++) { - Vector2 prev_p = curve->get_point_position(i); + _cached_draw_pts.resize(curve->get_point_count() * 8); + int count = 0; - for (int j = 1; j <= 8; j++) { - real_t frac = j / 8.0; + for (int i = 0; i < curve->get_point_count(); i++) { + for (int j = 0; j < 8; j++) { + real_t frac = j * (1.0 / 8.0); Vector2 p = curve->interpolate(i, frac); - draw_line(prev_p, p, color, line_width, true); - prev_p = p; + _cached_draw_pts.set(count++, p); } } + + draw_polyline(_cached_draw_pts, color, line_width, true); } } diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index bcd4a7034c..96df62538e 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -38,6 +38,7 @@ class Path2D : public Node2D { GDCLASS(Path2D, Node2D); Ref curve; + Vector _cached_draw_pts; void _curve_changed(); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 6a32577327..7a837343dd 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -448,6 +448,49 @@ void VisualServerCanvas::canvas_item_set_update_when_visible(RID p_item, bool p_ } void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width, bool p_antialiased) { + // Try drawing as a poly, because polys are batched and thus should run faster than thick lines, + // which run extremely slowly. + if (!p_antialiased && (p_width > 1.0)) { + // use poly drawing, as it is faster as it can use batching + static Vector points; + static Vector colors; + static Vector uvs; + if (points.size() != 4) { + // this should only be done once at runtime due to use of a static + points.resize(4); + colors.resize(4); + uvs.resize(4); + } + + Vector2 side = p_to - p_from; + real_t length = side.length(); + if (length == 0.0) { + // Not sure yet whether zero length is a noop operation later on, + // watch for visual errors. If there are visual errors, pass through + // to the line drawing routine below. + return; + } + + // normalize + side /= length; + + // 90 degrees + side = Vector2(-side.y, side.x); + side *= p_width; + + points.set(0, p_from + side); + points.set(1, p_from - side); + points.set(2, p_to - side); + points.set(3, p_to + side); + + for (int n = 0; n < 4; n++) { + colors.set(n, p_color); + } + + canvas_item_add_polygon(p_item, points, colors, uvs, RID(), RID(), false); + return; + } + Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item);