Godot: Inconsistent behavior of draw_line function

Created on 4 Aug 2020  路  10Comments  路  Source: godotengine/godot

Godot version:
3.2.2, 4.0

OS/device including version:
Any

Issue description:
I wanted to fix #35384, but I ran into the fact that draw_line seems to behave incorrectly too.

  • If I draw 1 pixel, then it is important that the second vector does not coincide with the first.
  • If I draw a horizontal (or vertical) line 1 pixel thick, it doesn't matter.
  • If the thickness is greater than 1, then it is important.
  • I have not tested the sloped lines.

Steps to reproduce:

func _draw():
    draw_line(Vector2(00, 00), Vector2(00+1, 00+1), Color.red)
    draw_line(Vector2(20, 00), Vector2(20+0, 00+0), Color.blue)

    draw_line(Vector2(00, 10), Vector2(00+8, 10+0), Color.green)
    draw_line(Vector2(20, 10), Vector2(20+8, 10+1), Color.yellow)

    draw_line(Vector2(00, 20), Vector2(00+8, 20+0), Color.cyan, 2)
    draw_line(Vector2(20, 20), Vector2(20+8, 20+1), Color.pink, 2)

image

Minimal reproduction project:
draw_line_bug.zip

rendering

All 10 comments

I tried to repeat these commands manually with given coordinates in KolourPaint. Here's what happened:

kolourpaint

Of course, KolourPaint is not an absolute authority, but the overall result is more logical. (Why the result is not the same as in the following figure, I don't know.)

image

Can you try it with pixel snap on? Also offsetting positions by 0.5 might help. E.g. try:

draw_line(Vector2(0.5, 0.5), Vector2(0.5+1, 0.5+1), Color.red)

Godot isnt a pixel art application. It uses the GPU to rasterize lines rather than drawing them pixel by pixel. So some differences are accepted and natural. Try the above tips and let me know how it goes.

'Use Pixel Snap' has no effect on this behavior.

Also offsetting positions by 0.5 might help. E.g. try:

draw_line(Vector2(0.5, 0.5), Vector2(0.5+1, 0.5+1), Color.red)

No. You probably don't quite understand what I mean. :smiley:

It uses the GPU to rasterize lines rather than drawing them pixel by pixel.

It doesn't matter how Godot draws the line. The problem is a strange and ambiguous coordinate system.

So some differences are accepted and natural.

Why then does draw_rect(Rect2(x,y,w,h), Color.blue) always draw the rectangle exactly as expected?

Why then does draw_rect(Rect2(x,y,w,h), Color.blue) always draw the rectangle exactly as expected?

Because GPUs handle lines and rects differently. For clarity, Godot doesn't handle drawing the line. It just passes the info off to the GPU to draw. So we need to work around how the GPU chooses to draw the line.

@dalexeev, that's how lines from your example would look before rasterization:

Godot_v3 2 2-stable_win64_bihGMQn2KY

Here's your a little expanded project:
draw_line.zip

I don't see inconsistency in here.

@kleonc Thank you, now I understand. The coordinates are the vertices of the grid, not the cells. @clayjohn was right.

This information should be documented. Also, we should probably create a similar function that works with pixel coordinates.

pixel       GPU
coords      coords
----------------------------
from to     from    to
----------------------------
(0,0-0,0 -> 0.0,0.5-1.0,0.5)
(0,0-0,0 -> 0.5,0.0-0.5,1.0)
 0,0-0,0 -> 0.0,0.0-1.0,1.0
 0,0-3,0 -> 0.0,0.5-4.0,0.5
 0,0-0,3 -> 0.5,0.0-0.5,4.0
 0,0-3,3 -> 0.0,0.0-4.0,4.0

image

In HTML5 canvas, a trick I've seen for working in pixel coordinates is to add Vector2(0.5, 0.5) to all coordinates.

Not that this trick works in Godot..
image

I also tested some slight variations, such as subtracting (instead of adding) the same offset from the top-left point of the line, computing the offset based on the direction of the line, etc. They didn't quite work out, however.

In HTML5 canvas, a trick I've seen for working in pixel coordinates is to add Vector2(0.5, 0.5) to all coordinates.

Not that this trick works in Godot..

@bojidar-bg I think the point is that you also need to take into account the direction (angle of inclination) of the line.

This difference in coordinates seems to be the cause of the bold lines in 4.0.

In 4.0, when width > 1, lines are drawn 2 times thicker than necessary, plus sometimes shifted up:

draw_line_4_0.zip

The problem with thick lines can be solved simply, just add the missing coefficient 0.5 in line 472:

https://github.com/godotengine/godot/blob/5100bb42ae92feff9d68d3ef080938980e666bbc/servers/rendering/rendering_server_canvas.cpp#L471-L477

But I still don't understand why the green line is drawn 1 px higher.

Was this page helpful?
0 / 5 - 0 ratings