SDL_RenderDrawLine endpoint inconsistency

I have a similar king of bug. I’m using sdl 2.0.8 on ubuntu 18.04.
When drawing line with either RenderDrawLine (or RenderDrawLines), the last pixel at the end of the line is not aligned.

I have not yet tried to upgrade to the latest version of SDL, nor tried on Windows.

I have the exact same problem. I found that the software renderer draws the line correctly SDL_RENDERER_SOFTWARE:

drawline-results

For straight lines I’ve resorted to SDL_RenderDrawPoint.

2 Likes

Thanks ! I’ll try that =)

I’m using 2.0.10 on ubuntu 20.04, and having the same issue. Does anyone know if this was corrected in recent SDL versions?

The relevant bug at Bugzilla says “target-2.0.16” so I assume this means it won’t be fixed until that release at the earliest. I don’t know why it is proving such a difficult nut to crack, but it may be that the various rendering backends simply aren’t consistent in their behavior.

My workaround has been to use SDL_RenderDrawPoints() which whilst not ideal is faster than calling SDL_RenderDrawPoint() multiple times.

yes, this is what I did, too. (using SDL_RenderDrawPoints())
I agree with you that this bug should have high priority.

1 Like

It was originally reported in December 2014. Perhaps they are trying to set a record for the longest time to fix a bug (six years and counting…) :grinning:

Here is my own test. Interestingly, the color of the non-aligned pixel is from the previous line, not the current one. The whole width of the line (including the non-aligned pixel) is correct (here 51px)

Zoom:
lines

Code:
#include <SDL2/SDL.h>

int main()
{
 
    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window * window = SDL_CreateWindow("SDL2 Line Drawing",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 500, 0);

    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderClear(renderer);

    SDL_SetRenderDrawColor(renderer, 10, 10, 255, 255);
    SDL_RenderDrawLine(renderer, 200, 200, 250, 200); // OK
    SDL_RenderDrawLine(renderer, 250, 210, 200, 210); // NOT OK
    SDL_RenderDrawLine(renderer, 200, 180, 200, 150); // OK
    SDL_RenderDrawLine(renderer, 250, 150, 250, 180); // OK

    SDL_SetRenderDrawColor(renderer, 255, 10, 10, 255);
    SDL_RenderDrawLine(renderer, 200, 300, 250, 300); // NOT OK
    SDL_RenderDrawLine(renderer, 250, 310, 200, 310); // NOT OK

    SDL_SetRenderDrawColor(renderer, 10, 255, 10, 255);
    SDL_RenderDrawLine(renderer, 200, 400, 250, 400); // NOT OK
    SDL_RenderDrawLine(renderer, 250, 410, 200, 410); // NOT OK

    SDL_RenderPresent(renderer);

    SDL_Delay(10000);

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}


/*
gcc line.c -lSDL2 -lSDL2main -o line
*/

The relevant bug at Bugzilla says “target-2.0.16”

Sorry, this was fixed for 2.0.14, but the bug report got forgotten (rather, there were several duplicates, and we missed one that got sorted into target-2.0.16).

The new 2.0.14 release has this fixed across all render backends.

(sorry in my previous post was still linking with an old SDL version.)
So I have dowloaded the current version, and indeed the mis-aligned point has disappeared, but there is still a problem. When the lines are drawn from right to left, they are not the same as when they’re drawn from left to right: namely they are shifted 1 pixel to the left.

Ouch, that’s actually worse: a fault at both ends rather than just one. :frowning_face:
Although I suppose if the workaround is to reverse the drawing direction, that’s not so bad.

Well, that’s infuriating. I’ll take a look.

my guess is that a badly defined rounding float -> int is used somewhere

this looks more difficult than what I thought; the openGL spec says explicitly that line segment rasterization need not be 1-pixel exact! See https://www.khronos.org/registry/OpenGL/specs/gl/glspec15.pdf, page 91:

“The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in either x or y window coordinates from a corresponding fragment produced by the diamond-exit rule”

While this seems ok for intermediate pixels, this seems completely silly for end-points, especially when these have integer coordinates.

Another difficulty is that the openGL line segment algorithm will not draw the last pixel (in order for it not to be repeated when a sequence of line segments are drawn). SDL’s solution to this is to make the last segment one pixel longer. So probably the bug comes from there. Not sure, but I don’t have time to investigate more today…

I feared as much. Empirically, SDL2 seems to be able to plot individual pixels correctly (SDL_RenderDrawPoints() has always worked for me) so maybe the most reliable approach would be for it to draw horizontal and vertical lines that way internally. With the batching mechanism, it might not hit performance too much.

Can you try the latest in revision control and see if it fixes this issue for you? I made a fix that should resolve this, but this all feels like it has a million corner cases.

1 Like

at least the code above now works as expected for me! thanks!

I will test my more elaborate graphics routines when I get the time

So on current tip i get this


This is also what is breaking rects SDL_RenderDrawRect not rectangular · Issue #4001 · libsdl-org/SDL · GitHub

Reverting opengl: More work on making line drawing match software renderer. · libsdl-org/SDL@b99543b · GitHub fixes this, but since @Sanette had issues with that version…??

For cross-reference purposes: SDL_RenderDrawRect function broken