From a85b000967ecc638da5dfa134636a95ddad40992 Mon Sep 17 00:00:00 2001 From: Yuri Roubinsky Date: Thu, 10 Feb 2022 11:40:16 +0300 Subject: [PATCH] Fix antialiasing for beginning/end of line in `canvas_item_add_polyline` --- servers/rendering/renderer_canvas_cull.cpp | 225 ++++++++++++++++++--- 1 file changed, 192 insertions(+), 33 deletions(-) diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 418d2bc42e9..29c02db5bda 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -601,42 +601,119 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vectoralloc_command(); - ERR_FAIL_COND(!pline_top); + PackedColorArray colors_begin_right_corner; + PackedVector2Array points_begin_right_corner; - Item::CommandPolygon *pline_bottom = canvas_item->alloc_command(); - ERR_FAIL_COND(!pline_bottom); + colors_begin_right_corner.resize(4); + points_begin_right_corner.resize(4); - //make three trianglestrip's for drawing the antialiased line... + PackedColorArray colors_end; + PackedVector2Array points_end; - Vector2 *points_top_ptr = points_top.ptrw(); - Vector2 *points_bottom_ptr = points_bottom.ptrw(); + colors_end.resize(4); + points_end.resize(4); - Color *colors_top_ptr = colors_top.ptrw(); - Color *colors_bottom_ptr = colors_bottom.ptrw(); + 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(pc2); + points_left.resize(pc2); + + PackedColorArray colors_right; + PackedVector2Array points_right; + + colors_right.resize(pc2); + points_right.resize(pc2); + + Item::CommandPolygon *pline_begin = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_begin); + + Item::CommandPolygon *pline_begin_left_corner = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_begin_left_corner); + + Item::CommandPolygon *pline_begin_right_corner = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_begin_right_corner); + + Item::CommandPolygon *pline_end = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_end); + + Item::CommandPolygon *pline_end_left_corner = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_end_left_corner); + + Item::CommandPolygon *pline_end_right_corner = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_end_right_corner); + + Item::CommandPolygon *pline_left = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_left); + + Item::CommandPolygon *pline_right = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_right); + + // Makes nine triangle strips for drawing the antialiased line. + + 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(); + + 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(); + Color *colors_right_ptr = colors_right.ptrw(); for (int i = 0, j = 0; i < pc; i++, j += 2) { + bool is_begin = i == 0; + bool is_end = i == pc - 1; + Vector2 t; - if (i == pc - 1) { + Vector2 end_border; + Vector2 begin_border; + if (is_end) { t = prev_t; + end_border = (p_points[i] - p_points[i - 1]).normalized() * border_size; } else { t = (p_points[i + 1] - p_points[i]).normalized().orthogonal(); - if (i == 0) { + if (is_begin) { prev_t = t; + begin_border = (p_points[i] - p_points[i + 1]).normalized() * border_size; } } @@ -644,17 +721,17 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vectorprimitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_top->polygon.create(indices, points_top, colors_top); + pline_begin->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline_begin->polygon.create(indices, points_begin, colors_begin); - pline_bottom->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; - pline_bottom->polygon.create(indices, points_bottom, colors_bottom); + 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); + + pline_right->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline_right->polygon.create(indices, points_right, colors_right); } else { - //make a trianglestrip for drawing the line... + // Makes a single triangle strip for drawing the line. for (int i = 0, j = 0; i < pc; i++, j += 2) { Vector2 t;