Restore antialiasing for `draw_line`

This commit is contained in:
Yuri Roubinsky 2022-04-11 20:42:46 +03:00
parent 5974e1432e
commit 6e9535a9c8
10 changed files with 182 additions and 19 deletions

View File

@ -103,8 +103,9 @@
<argument index="1" name="to" type="Vector2" /> <argument index="1" name="to" type="Vector2" />
<argument index="2" name="color" type="Color" /> <argument index="2" name="color" type="Color" />
<argument index="3" name="width" type="float" default="1.0" /> <argument index="3" name="width" type="float" default="1.0" />
<argument index="4" name="antialiased" type="bool" default="false" />
<description> <description>
Draws a line from a 2D point to another, with a given color and width. See also [method draw_multiline] and [method draw_polyline]. Draws a line from a 2D point to another, with a given color and width. It can be optionally antialiased. See also [method draw_multiline] and [method draw_polyline].
</description> </description>
</method> </method>
<method name="draw_mesh"> <method name="draw_mesh">
@ -191,7 +192,7 @@
<argument index="2" name="width" type="float" default="1.0" /> <argument index="2" name="width" type="float" default="1.0" />
<argument index="3" name="antialiased" type="bool" default="false" /> <argument index="3" name="antialiased" type="bool" default="false" />
<description> <description>
Draws interconnected line segments with a uniform [code]color[/code] and [code]width[/code]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline] instead. See also [method draw_polygon]. Draws interconnected line segments with a uniform [code]color[/code] and [code]width[/code] and optional antialiasing. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline] instead. See also [method draw_polygon].
</description> </description>
</method> </method>
<method name="draw_polyline_colors"> <method name="draw_polyline_colors">
@ -201,7 +202,7 @@
<argument index="2" name="width" type="float" default="1.0" /> <argument index="2" name="width" type="float" default="1.0" />
<argument index="3" name="antialiased" type="bool" default="false" /> <argument index="3" name="antialiased" type="bool" default="false" />
<description> <description>
Draws interconnected line segments with a uniform [code]width[/code] and segment-by-segment coloring. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline_colors] instead. See also [method draw_polygon]. Draws interconnected line segments with a uniform [code]width[/code] and segment-by-segment coloring, and optional antialiasing. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline_colors] instead. See also [method draw_polygon].
</description> </description>
</method> </method>
<method name="draw_primitive"> <method name="draw_primitive">

View File

@ -183,6 +183,7 @@
<argument index="2" name="to" type="Vector2" /> <argument index="2" name="to" type="Vector2" />
<argument index="3" name="color" type="Color" /> <argument index="3" name="color" type="Color" />
<argument index="4" name="width" type="float" default="1.0" /> <argument index="4" name="width" type="float" default="1.0" />
<argument index="5" name="antialiased" type="bool" default="false" />
<description> <description>
</description> </description>
</method> </method>

View File

@ -463,10 +463,10 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, off, p_to, p_color, p_width); RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, off, p_to, p_color, p_width);
} }
void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width) { void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
} }
void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) { void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
@ -883,7 +883,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent); ClassDB::bind_method(D_METHOD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent);
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled); ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width"), &CanvasItem::draw_line, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash"), &CanvasItem::draw_dashed_line, DEFVAL(1.0), DEFVAL(2.0)); ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash"), &CanvasItem::draw_dashed_line, DEFVAL(1.0), DEFVAL(2.0));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));

View File

@ -215,7 +215,7 @@ public:
/* DRAWING API */ /* DRAWING API */
void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, real_t p_dash = 2.0); void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, real_t p_dash = 2.0);
void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0); void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false); void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0, bool p_antialiased = false); void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0, bool p_antialiased = false);
void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false); void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);

View File

@ -82,7 +82,7 @@ void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) {
if (is_collision_outline_enabled()) { if (is_collision_outline_enabled()) {
RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
// Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`.
RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color, 1.0, true);
} }
} }

View File

@ -552,27 +552,188 @@ void RendererCanvasCull::canvas_item_set_update_when_visible(RID p_item, bool p_
canvas_item->update_when_visible = p_update; canvas_item->update_when_visible = p_update;
} }
void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) { void RendererCanvasCull::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) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item); Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item); ERR_FAIL_COND(!canvas_item);
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>(); Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!line); ERR_FAIL_COND(!line);
Vector2 diff = (p_from - p_to);
Vector2 dir = diff.orthogonal().normalized();
Vector2 t = dir * p_width * 0.5;
Vector2 begin_left;
Vector2 begin_right;
Vector2 end_left;
Vector2 end_right;
if (p_width > 1.001) { if (p_width > 1.001) {
Vector2 t = (p_from - p_to).orthogonal().normalized() * p_width * 0.5; begin_left = p_from + t;
line->points[0] = p_from + t; begin_right = p_from - t;
line->points[1] = p_from - t; end_left = p_to + t;
line->points[2] = p_to - t; end_right = p_to - t;
line->points[3] = p_to + t;
line->points[0] = begin_left;
line->points[1] = begin_right;
line->points[2] = end_right;
line->points[3] = end_left;
line->point_count = 4; line->point_count = 4;
} else { } else {
line->point_count = 2; begin_left = p_from;
begin_right = p_from;
end_left = p_to;
end_right = p_to;
line->points[0] = p_from; line->points[0] = p_from;
line->points[1] = p_to; line->points[1] = p_to;
line->point_count = 2;
} }
for (uint32_t i = 0; i < line->point_count; i++) { for (uint32_t i = 0; i < line->point_count; i++) {
line->colors[i] = p_color; line->colors[i] = p_color;
} }
if (p_antialiased) {
float border_size = 2.0;
if (p_width < border_size) {
border_size = p_width;
}
Vector2 dir2 = diff.normalized();
Vector2 border = dir * border_size;
Vector2 border2 = dir2 * border_size;
Color transparent = Color(p_color.r, p_color.g, p_color.b, 0.0);
{
Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!left_border);
left_border->points[0] = begin_left;
left_border->points[1] = begin_left + border;
left_border->points[2] = end_left + border;
left_border->points[3] = end_left;
left_border->colors[0] = p_color;
left_border->colors[1] = transparent;
left_border->colors[2] = transparent;
left_border->colors[3] = p_color;
left_border->point_count = 4;
}
{
Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!right_border);
right_border->points[0] = begin_right;
right_border->points[1] = begin_right - border;
right_border->points[2] = end_right - border;
right_border->points[3] = end_right;
right_border->colors[0] = p_color;
right_border->colors[1] = transparent;
right_border->colors[2] = transparent;
right_border->colors[3] = p_color;
right_border->point_count = 4;
}
{
Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!top_border);
top_border->points[0] = begin_left;
top_border->points[1] = begin_left + border2;
top_border->points[2] = begin_right + border2;
top_border->points[3] = begin_right;
top_border->colors[0] = p_color;
top_border->colors[1] = transparent;
top_border->colors[2] = transparent;
top_border->colors[3] = p_color;
top_border->point_count = 4;
}
{
Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!bottom_border);
bottom_border->points[0] = end_left;
bottom_border->points[1] = end_left - border2;
bottom_border->points[2] = end_right - border2;
bottom_border->points[3] = end_right;
bottom_border->colors[0] = p_color;
bottom_border->colors[1] = transparent;
bottom_border->colors[2] = transparent;
bottom_border->colors[3] = p_color;
bottom_border->point_count = 4;
}
{
Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!top_left_corner);
top_left_corner->points[0] = begin_left;
top_left_corner->points[1] = begin_left + border2;
top_left_corner->points[2] = begin_left + border + border2;
top_left_corner->points[3] = begin_left + border;
top_left_corner->colors[0] = p_color;
top_left_corner->colors[1] = transparent;
top_left_corner->colors[2] = transparent;
top_left_corner->colors[3] = transparent;
top_left_corner->point_count = 4;
}
{
Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!top_right_corner);
top_right_corner->points[0] = begin_right;
top_right_corner->points[1] = begin_right + border2;
top_right_corner->points[2] = begin_right - border + border2;
top_right_corner->points[3] = begin_right - border;
top_right_corner->colors[0] = p_color;
top_right_corner->colors[1] = transparent;
top_right_corner->colors[2] = transparent;
top_right_corner->colors[3] = transparent;
top_right_corner->point_count = 4;
}
{
Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!bottom_left_corner);
bottom_left_corner->points[0] = end_left;
bottom_left_corner->points[1] = end_left - border2;
bottom_left_corner->points[2] = end_left + border - border2;
bottom_left_corner->points[3] = end_left + border;
bottom_left_corner->colors[0] = p_color;
bottom_left_corner->colors[1] = transparent;
bottom_left_corner->colors[2] = transparent;
bottom_left_corner->colors[3] = transparent;
bottom_left_corner->point_count = 4;
}
{
Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!bottom_right_corner);
bottom_right_corner->points[0] = end_right;
bottom_right_corner->points[1] = end_right - border2;
bottom_right_corner->points[2] = end_right - border - border2;
bottom_right_corner->points[3] = end_right - border;
bottom_right_corner->colors[0] = p_color;
bottom_right_corner->colors[1] = transparent;
bottom_right_corner->colors[2] = transparent;
bottom_right_corner->colors[3] = transparent;
bottom_right_corner->point_count = 4;
}
}
} }
void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {

View File

@ -215,7 +215,7 @@ public:
void canvas_item_set_update_when_visible(RID p_item, bool p_update); void canvas_item_set_update_when_visible(RID p_item, bool p_update);
void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0); void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0); void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);

View File

@ -799,7 +799,7 @@ public:
FUNC2(canvas_item_set_draw_behind_parent, RID, bool) FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float) FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)

View File

@ -2566,7 +2566,7 @@ void RenderingServer::_bind_methods() {
/* Primitives */ /* Primitives */
ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect); ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);

View File

@ -1293,7 +1293,7 @@ public:
NINE_PATCH_TILE_FIT, NINE_PATCH_TILE_FIT,
}; };
virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0) = 0; virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0; virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0) = 0; virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0) = 0;
virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;