How to properly draw a 1px wide line at any angle? (possible bug)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Von_Bednar

Example of the issue.

I am working on a low-fi pixel platformer with grapple hook mechanic and I am trying to draw the rope of the grappling hook. I want the line to be 1px. Currently I am using a Line2D node for it, but I am having issues with the line rendering

As seen above, the line is shifting weight and is “breaking” at certain angles. I thought maybe the line drawing is not in sync with the rest of drawing. I have tried putting changes to the line inside _physics_process() in hopes it will sync the rendering, and while it seems to improve it a little, it doesn’t solve the problem - the line still changes width, breaks and now flickers (goes invisible on some frames)!

Then I thought it might be the fault of the camera, but disabling camera makes it even worse - the line is only visible only during the frames when it is perfectly straight.

I have also tried making the line wider by a decimal (width of 1.1 to 1.9). It makes the rope stay visible for sure, but it definitely makes the rope thicker (more segments are 2px than 1px, less so with something 1.1 but still the rope as a whole is thicker than 1pixel), and it still jiggles and flickers.

Now my thinking is that Line2D maybe is not meant to be used at runtime to generate graphics. Maybe there is another approach I am missing? Or is this a bug in the engine? I mean, it should be an easy task to draw a 1px line at any angle, but I am at my wits end.

I am open to any suggestions, either using Line2D or any other approach.

Just in case my settings can help / are relevant:

Godot 3.1
GLES2
Use Nvidia Flicker workaround checked
Pixel snap checked (this is needed for my game, disabling it helps, but the line still flickers and jiggles on top of other unwanted tileset behavior)
Mode: Viewport
Aspect: Keep

I’ve never had that problem so maybe check your renders settings.

Merlin1846 | 2020-01-30 00:53

I was using the default settings (except the ones specified above). Any particular settings I should pay attention to?

Von_Bednar | 2020-01-30 01:27

I’m not sure. I’ve never had this problem.

Merlin1846 | 2020-01-30 20:07

Maybe it’s the Z-index?

Because sometimes it fixes it’s self and it looks like almost as if somethings blocking it.

Merlin1846 | 2020-01-30 20:08

:bust_in_silhouette: Reply From: fizzyted

I have a similar 1px line using Line2D. This effect happens because Godot has been instructed to only ever draw one pixel, and at some angles that results in “missing” parts of the line.

You can draw a smooth line if you enable the antialiased property of Line2D, which will fill in the “missing” pixels with lighter colored ones to blend. This style might not work if you are going for a real arcade-y vibe, but it should help keep the line very thin but visible.

:bust_in_silhouette: Reply From: Hapiel

It appears to be a problem with GLES3. If you set your renderer to GLES2 it works on my end, with 3 I have the same issue you have.

See also: Line2d's antialiased is not working correctly in GLES 3 · Issue #38872 · godotengine/godot · GitHub

:bust_in_silhouette: Reply From: dairin0d

I’ve been pondering a similar question myself, and recently realized that it can be done manually. Just in case it’s still relevant (or someone else encounters the same problem):

You might be able to emulate a “pixel-perfect” line by using a rectangular polygon in its place, whose thickness is

EffectiveThickness = LineThickness - 1 + max(abs(Direction.x), abs(Direction.y))

where LineThickness how wide you want your line to be (e.g. 1px), and Direction is the normalized direction of the line.