From f29e39cfd64b98de4968b974be5a738d5bdfb941 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Thu, 19 Jan 2023 17:08:19 +0100 Subject: [PATCH] RendererCanvasCull Simplify drawing antialiased polyline --- servers/rendering/renderer_canvas_cull.cpp | 233 ++++++--------------- 1 file changed, 68 insertions(+), 165 deletions(-) diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 4265ee5518f..be34bdffa79 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -851,8 +851,9 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point PackedColorArray colors; PackedVector2Array points; - colors.resize(polyline_point_count); - points.resize(polyline_point_count); + // Additional 2+2 vertices to antialias begin+end of the middle triangle strip. + colors.resize(polyline_point_count + ((p_antialiased && !loop) ? 4 : 0)); + points.resize(polyline_point_count + ((p_antialiased && !loop) ? 4 : 0)); Vector2 *points_ptr = points.ptrw(); Color *colors_ptr = colors.ptrw(); @@ -868,96 +869,30 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point } Color color2 = Color(1, 1, 1, 0); - PackedColorArray colors_begin; - PackedVector2Array points_begin; - - colors_begin.resize(4); - points_begin.resize(4); - - PackedColorArray colors_begin_left_corner; - PackedVector2Array points_begin_left_corner; - - colors_begin_left_corner.resize(4); - points_begin_left_corner.resize(4); - - PackedColorArray colors_begin_right_corner; - PackedVector2Array points_begin_right_corner; - - colors_begin_right_corner.resize(4); - points_begin_right_corner.resize(4); - - PackedColorArray colors_end; - PackedVector2Array points_end; - - colors_end.resize(4); - points_end.resize(4); - - PackedColorArray colors_end_left_corner; - PackedVector2Array points_end_left_corner; - - colors_end_left_corner.resize(4); - points_end_left_corner.resize(4); - - PackedColorArray colors_end_right_corner; - PackedVector2Array points_end_right_corner; - - colors_end_right_corner.resize(4); - points_end_right_corner.resize(4); - - PackedColorArray colors_left; - PackedVector2Array points_left; - - colors_left.resize(polyline_point_count); - points_left.resize(polyline_point_count); - - PackedColorArray colors_right; - PackedVector2Array points_right; - - colors_right.resize(polyline_point_count); - points_right.resize(polyline_point_count); - - Item::CommandPolygon *pline_begin = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_COND(!pline_begin); - - Item::CommandPolygon *pline_begin_left_corner = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_COND(!pline_begin_left_corner); - - Item::CommandPolygon *pline_begin_right_corner = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_COND(!pline_begin_right_corner); - - Item::CommandPolygon *pline_end = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_COND(!pline_end); - - Item::CommandPolygon *pline_end_left_corner = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_COND(!pline_end_left_corner); - - Item::CommandPolygon *pline_end_right_corner = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_COND(!pline_end_right_corner); - Item::CommandPolygon *pline_left = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!pline_left); Item::CommandPolygon *pline_right = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!pline_right); - // Makes nine triangle strips for drawing the antialiased line. + PackedColorArray colors_left; + PackedVector2Array points_left; - Vector2 *points_begin_ptr = points_begin.ptrw(); - Vector2 *points_begin_left_corner_ptr = points_begin_left_corner.ptrw(); - Vector2 *points_begin_right_corner_ptr = points_begin_right_corner.ptrw(); - Vector2 *points_end_ptr = points_end.ptrw(); - Vector2 *points_end_left_corner_ptr = points_end_left_corner.ptrw(); - Vector2 *points_end_right_corner_ptr = points_end_right_corner.ptrw(); - Vector2 *points_left_ptr = points_left.ptrw(); - Vector2 *points_right_ptr = points_right.ptrw(); + PackedColorArray colors_right; + PackedVector2Array points_right; + + // 2+2 additional vertices for begin+end corners. + // 1 additional vertex to swap the orientation of the triangles within the end corner's quad. + colors_left.resize(polyline_point_count + (loop ? 0 : 5)); + points_left.resize(polyline_point_count + (loop ? 0 : 5)); + + colors_right.resize(polyline_point_count + (loop ? 0 : 5)); + points_right.resize(polyline_point_count + (loop ? 0 : 5)); - Color *colors_begin_ptr = colors_begin.ptrw(); - Color *colors_begin_left_corner_ptr = colors_begin_left_corner.ptrw(); - Color *colors_begin_right_corner_ptr = colors_begin_right_corner.ptrw(); - Color *colors_end_ptr = colors_end.ptrw(); - Color *colors_end_left_corner_ptr = colors_end_left_corner.ptrw(); - Color *colors_end_right_corner_ptr = colors_end_right_corner.ptrw(); Color *colors_left_ptr = colors_left.ptrw(); + Vector2 *points_left_ptr = points_left.ptrw(); + + Vector2 *points_right_ptr = points_right.ptrw(); Color *colors_right_ptr = colors_right.ptrw(); Vector2 prev_segment_dir; @@ -985,118 +920,86 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point Vector2 border = base_edge_offset * border_size; Vector2 pos = p_points[i]; - points_ptr[i * 2 + 0] = pos + edge_offset; - points_ptr[i * 2 + 1] = pos - edge_offset; + int j = i * 2 + (loop ? 0 : 2); - points_left_ptr[i * 2 + 0] = pos + edge_offset + border; - points_left_ptr[i * 2 + 1] = pos + edge_offset; + points_ptr[j + 0] = pos + edge_offset; + points_ptr[j + 1] = pos - edge_offset; - points_right_ptr[i * 2 + 0] = pos - edge_offset; - points_right_ptr[i * 2 + 1] = pos - edge_offset - border; + points_left_ptr[j + 0] = pos + edge_offset; + points_left_ptr[j + 1] = pos + edge_offset + border; + + points_right_ptr[j + 0] = pos - edge_offset; + points_right_ptr[j + 1] = pos - edge_offset - border; if (i < p_colors.size()) { color = p_colors[i]; color2 = Color(color.r, color.g, color.b, 0); } - colors_ptr[i * 2 + 0] = color; - colors_ptr[i * 2 + 1] = color; + colors_ptr[j + 0] = color; + colors_ptr[j + 1] = color; - colors_left_ptr[i * 2 + 0] = color2; - colors_left_ptr[i * 2 + 1] = color; + colors_left_ptr[j + 0] = color; + colors_left_ptr[j + 1] = color2; - colors_right_ptr[i * 2 + 0] = color; - colors_right_ptr[i * 2 + 1] = color2; + colors_right_ptr[j + 0] = color; + colors_right_ptr[j + 1] = color2; - if (is_first_point) { - Vector2 begin_border = loop ? Vector2() : -segment_dir * border_size; + if (is_first_point && !loop) { + Vector2 begin_border = -segment_dir * border_size; - points_begin_ptr[0] = pos + edge_offset + begin_border; - points_begin_ptr[1] = pos - edge_offset + begin_border; - points_begin_ptr[2] = pos + edge_offset; - points_begin_ptr[3] = pos - edge_offset; + points_ptr[0] = pos + edge_offset + begin_border; + points_ptr[1] = pos - edge_offset + begin_border; - colors_begin_ptr[0] = color2; - colors_begin_ptr[1] = color2; - colors_begin_ptr[2] = color; - colors_begin_ptr[3] = color; + colors_ptr[0] = color2; + colors_ptr[1] = color2; - points_begin_left_corner_ptr[0] = pos - edge_offset - border; - points_begin_left_corner_ptr[1] = pos - edge_offset + begin_border - border; - points_begin_left_corner_ptr[2] = pos - edge_offset; - points_begin_left_corner_ptr[3] = pos - edge_offset + begin_border; + points_left_ptr[0] = pos + edge_offset + begin_border; + points_left_ptr[1] = pos + edge_offset + begin_border + border; - colors_begin_left_corner_ptr[0] = color2; - colors_begin_left_corner_ptr[1] = color2; - colors_begin_left_corner_ptr[2] = color; - colors_begin_left_corner_ptr[3] = color2; + colors_left_ptr[0] = color2; + colors_left_ptr[1] = color2; - points_begin_right_corner_ptr[0] = pos + edge_offset + begin_border; - points_begin_right_corner_ptr[1] = pos + edge_offset + begin_border + border; - points_begin_right_corner_ptr[2] = pos + edge_offset; - points_begin_right_corner_ptr[3] = pos + edge_offset + border; + points_right_ptr[0] = pos - edge_offset + begin_border; + points_right_ptr[1] = pos - edge_offset + begin_border - border; - colors_begin_right_corner_ptr[0] = color2; - colors_begin_right_corner_ptr[1] = color2; - colors_begin_right_corner_ptr[2] = color; - colors_begin_right_corner_ptr[3] = color2; + colors_right_ptr[0] = color2; + colors_right_ptr[1] = color2; } - if (is_last_point) { - Vector2 end_border = loop ? Vector2() : prev_segment_dir * border_size; + if (is_last_point && !loop) { + Vector2 end_border = prev_segment_dir * border_size; + int end_index = polyline_point_count + 2; - points_end_ptr[0] = pos + edge_offset + end_border; - points_end_ptr[1] = pos - edge_offset + end_border; - points_end_ptr[2] = pos + edge_offset; - points_end_ptr[3] = pos - edge_offset; + points_ptr[end_index + 0] = pos + edge_offset + end_border; + points_ptr[end_index + 1] = pos - edge_offset + end_border; - colors_end_ptr[0] = color2; - colors_end_ptr[1] = color2; - colors_end_ptr[2] = color; - colors_end_ptr[3] = color; + colors_ptr[end_index + 0] = color2; + colors_ptr[end_index + 1] = color2; - points_end_left_corner_ptr[0] = pos - edge_offset - border; - points_end_left_corner_ptr[1] = pos - edge_offset + end_border - border; - points_end_left_corner_ptr[2] = pos - edge_offset; - points_end_left_corner_ptr[3] = pos - edge_offset + end_border; + // Swap orientation of the triangles within both end corner quads so the visual seams + // between triangles goes from the edge corner. Done by going back to the edge corner + // (1 additional vertex / zero-area triangle per left/right corner). + points_left_ptr[end_index + 0] = pos + edge_offset; + points_left_ptr[end_index + 1] = pos + edge_offset + end_border + border; + points_left_ptr[end_index + 2] = pos + edge_offset + end_border; - colors_end_left_corner_ptr[0] = color2; - colors_end_left_corner_ptr[1] = color2; - colors_end_left_corner_ptr[2] = color; - colors_end_left_corner_ptr[3] = color2; + colors_left_ptr[end_index + 0] = color; + colors_left_ptr[end_index + 1] = color2; + colors_left_ptr[end_index + 2] = color2; - points_end_right_corner_ptr[0] = pos + edge_offset + end_border; - points_end_right_corner_ptr[1] = pos + edge_offset + end_border + border; - points_end_right_corner_ptr[2] = pos + edge_offset; - points_end_right_corner_ptr[3] = pos + edge_offset + border; + points_right_ptr[end_index + 0] = pos - edge_offset; + points_right_ptr[end_index + 1] = pos - edge_offset + end_border - border; + points_right_ptr[end_index + 2] = pos - edge_offset + end_border; - colors_end_right_corner_ptr[0] = color2; - colors_end_right_corner_ptr[1] = color2; - colors_end_right_corner_ptr[2] = color; - colors_end_right_corner_ptr[3] = color2; + colors_right_ptr[end_index + 0] = color; + colors_right_ptr[end_index + 1] = color2; + colors_right_ptr[end_index + 2] = color2; } prev_segment_dir = segment_dir; } - pline_begin->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_begin->polygon.create(indices, points_begin, colors_begin); - - pline_begin_left_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_begin_left_corner->polygon.create(indices, points_begin_left_corner, colors_begin_left_corner); - - pline_begin_right_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_begin_right_corner->polygon.create(indices, points_begin_right_corner, colors_begin_right_corner); - - pline_end->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_end->polygon.create(indices, points_end, colors_end); - - pline_end_left_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_end_left_corner->polygon.create(indices, points_end_left_corner, colors_end_left_corner); - - pline_end_right_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_end_right_corner->polygon.create(indices, points_end_right_corner, colors_end_right_corner); - pline_left->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; pline_left->polygon.create(indices, points_left, colors_left);