Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gfx_Line Draws a different line when endpoints are swapped and one is offscreen #471

Open
LukeBorowy opened this issue Jan 23, 2024 · 2 comments

Comments

@LukeBorowy
Copy link

LukeBorowy commented Jan 23, 2024

When drawing a line, the result changes depending on which endpoint is specified first. This bug only occurs if one of the endpoints is offscreen.

Actual behavior: The left endpoint of the lines is separated somehow in the process of clipping to screen, so the two lines are drawn visibly differently.
Expected behavior: They should draw the same way, so this code would only show a red line.

#include <ti/getcsc.h>
#include <graphx.h>

int main(void)
{
    gfx_Begin();

    gfx_SetColor(7); // green
    gfx_Line(-100, 20, 30, 40);

    gfx_SetColor(224); // red
    gfx_Line(30, 40, -100, 20); // same numbers as above, just flipped order

    while (!os_GetCSC());

    gfx_End();

    return 0;
}

Result:
image

Closeup where you can see the divergence:
image

It may look minor here, but in my game I am often doing this with different colors connecting to things off screen when the camera is moving, and this bug looks bad and causes color flickering.

@LukeBorowy LukeBorowy changed the title gfx_Line Draws a different line when endpoints are reversed and one is offscreen gfx_Line Draws a different line when endpoints are swapped and one is offscreen Jan 23, 2024
@LukeBorowy
Copy link
Author

Note that this occurs on all 4 edges of the screen, not just going off to the left. For example, going off the top or bottom will vary in the x-coordinate instead.

@LukeBorowy
Copy link
Author

LukeBorowy commented Jan 24, 2024

Ok, I've been testing things out to try to pinpoint this bug. I saw that the graphx code was using the Cohen Sutherland algorithm to clip the lines into frame. I found a C implementation and was testing to see if it exhibited the same bug as the graphx one.
The issue seems to occur here in the algorithm:

y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0);

It did show the same bug, although it was only off by 1 pixel when graphx was off by 2. However, I think the underlying cause is the same: Signed integer division truncates towards 0. This means that when the denominator is negative, as in the red case, 0.61 pixel is not subtracted, so it ends up with y being 1 greater, and the lines don't match up. Maybe in the assembly version this happens twice for some reason so it is off by 2.

I think that if there was a division that rounds strictly down instead of toward 0, and used instead of _DivideHLBC in the gfx_Line function, it would solve this bug. However, I don't know assembly or if that would be significantly slower.
Alternatively, I've just been using this:

void gfx_ConsistentLine(int x0, int y0, int x1, int y1) {
    if (x0 < x1) {
        gfx_Line(x0, y0, x1, y1);
    } else {
        gfx_Line(x1, y1, x0, y0);
    }
}

It will make sure the same endpoint is put first. In the case of a vertical line it couldn't tell, but the bug doesn't happen with a vertical line so it's ok.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants