When using the line tool or shift+clicking with a brush, I expect the lines to be built out of segments that are as equally-sized as possible so that the lines appear as straight as possible, but Aseprite produces rather irregular lines:
Dark blue: correct line segments, where the length of the segment matches the expected segment length for that slope.
Red: incorrect/irregular line segments, shorter or longer than expected.
This makes the lines appear less straight than they could be, and I have to either hand-draw the line segments myself or edit Aseprite’s results to get straight, clean lines.
This appears to be a fairly common issue (I saw similar problems in GIMP, Photoshop, and Tiled) and I suspect it’s an artefact of Bresenham line algorithm’s error accumulation reaching the limit at weird times. For most slopes irregular line segments are to be expected so they’re less noticeable, but for lines like this, with 1:n or n:1 slopes, the irregularity is very noticeable, and makes a big difference for pixel art.
Yeah it’s a problem with the line tool. Related issue: Ability to snap line tool to more angles · Issue #1641 · aseprite/aseprite · GitHub
I think rather than snapping to angles, I think a pixel-perfect mode for the line where it can only draw equal sized step lines would be a good solution.
Hi there actually it was something I was playing a lot in the past, I came to the conclusion that the line algorithm used in most programs (including Aseprite now) is the best one (?) to draw continuous lines (e.g. the regular freehand stroke, or one line after the other). (Where the starting error of the Bresenham algorithm depends on the width+height of the line instead of starting in 0).
I think we need some kind of switch to use perfect lines or not in these cases.
A comment about the current line algorithm in the code:
// Useful to create continuous lines (you can draw from one point to
// another, and continue from that point to another in the same
// angle and the line will look continous).
The lead dev of Tiled was working on this issue earlier (hearing about that is what prompted me to post this) and seems to have arrived at a rather good solution that changes the starting error based on the slope of the line:
The starting error change leads to the line halting early, hence the extension of the target y coordinate by 1.
I played around with it and I think the results are quite satisfactory:
Tiled’s algorithm deals with the error a little differently (and did so even before this change), but perhaps there’s something useful you can find in their code.
I will try to show the problem with the “perfect blocks” pixel algorithm:
In all cases the lines are painted with a rectangle of 9x3 from top-left to bottom-right. The first case is the “perfect blocks” (3 blocks of 3x1 that makes the 9x3 line). If you see, the line itself is perfect, but these blocks cannot be put together to form a continuous line, e.g. Pencil tool, Shift+click to draw 3 lines of the same size/slope to continue the stroke).
In the second case (the current Aseprite algorithm, and most regular painting programs), you can see how the line looks uniform (the same process). But isolated it doesn’t make too much sense.
So, in the past we have used the “perfect blocks” but it brought this issue.
What can we do? Basically this cannot be solved automatically by an algorithm, it depends on the use case. Some users are expecting to draw regular continuous lines (Shift+clicking, or just using one end point as starting point of the next line), the current algorithm fits that case. And other users are expecting lines with “perfect blocks” (generally useful when drawing just one line or using as starting point the next expected point in the line).
At the moment the only way to use this “perfect blocks” mode in Aseprite is using Snap to Grid and configuring the grid appropriately:
We should offer an easier way to access to this functionality (maybe an option/checkbox in the context bar (“Pixel Perfect”?), or something like that for the Line tool).
I have personally found use cases for the “imperfect” lines, so I agree that having a toggle for different line generation modes would be the best option :>