-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[rshapes] DrawRectangleLines()
missing pixel in lower right corner
#4756
Comments
@Roucou I'm afraid Environment and Screenshot data are required to track this issue |
Running on Linux desktop: INFO: Initializing raylib 5.6-dev Screenshot: |
@Roucou The line with the missing pixel in the screenshot does not seem to be a 1px border line drawn using |
I don't see this problem on my end. This might be an issue with underlying OpenGL implementation. Here's how it looks like on my side (Arch Linux x86_64 with Xorg and proprietary Nvidia drivers): Notice that in my case I'm using proprietary Nvidia drivers while OP is using Mesa Intel drivers which might be the reason why it looks different: Logs
|
I believe this is one of those super annoyances with OpenGL...
It seems that [EDIT] Current implementation of CC @raysan5 |
This might a problem with more shapes than RectangleLines. Out of curiosity, does this issue also occurs with |
I have been wondering if the FP rounding settings on float to int have an impact on these cases,, especially across (target) platforms and build systems. |
I played a bit with Maybe it happens somewhere deeper in |
Am doing some business travel the following days, will do some tests over the weekend. I did play around with switching to float instead of int earlier on, but that resulted in the same missing pixel. Also tried drawing the four lines individually using DrawLine(...) but that gave even weirder results. @sleeptightAnsiC is probably right, it might very well be basic OpenGL incompatibility issues. So, for my game I'll probably have to switch to textures as a workaround. But many thanks for the investigation! |
DrawRectangleLines()
missing pixel in lower right corner
@Roucou @sleeptightAnsiC I'm afraid this is a recurrent issue and unfortunately it's platform dependant, it depends on the OS, the GPU and the drivers. If solved for a specific case it can break for other cases. Already worked on it many many times... As a solution, you can use |
@Roucou despite that issue is closed, make sure to answer my questions when you'll have some opportunity, please. I may take a look at fixing/forwarding this anyway. |
Well, well, well... I was able to reproduce this on some very old hardware with iGPU: I tried to fix it by manipulating the offset used in If someone wishes to mess with this, here are... patch with this function refactored
diff --git a/src/rshapes.c b/src/rshapes.c
index 704d74f..ed628e9 100644
--- a/src/rshapes.c
+++ b/src/rshapes.c
@@ -807,23 +807,30 @@ void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Col
// but it solves another issue: https://github.com/raysan5/raylib/issues/3884
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
{
- Matrix mat = rlGetMatrixTransform();
- float xOffset = 0.5f/mat.m0;
- float yOffset = 0.5f/mat.m5;
+ const float x = (float)posX;
+ const float y = (float)posY;
+ const float w = (float)width;
+ const float h = (float)height;
+ const float o = 0.51; // offset
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
- rlVertex2f((float)posX + xOffset, (float)posY + yOffset);
- rlVertex2f((float)posX + (float)width - xOffset, (float)posY + yOffset);
- rlVertex2f((float)posX + (float)width - xOffset, (float)posY + yOffset);
- rlVertex2f((float)posX + (float)width - xOffset, (float)posY + (float)height - yOffset);
+ // top: left => right
+ rlVertex2f(x + o, y + o);
+ rlVertex2f(x + w - o, y + o);
- rlVertex2f((float)posX + (float)width - xOffset, (float)posY + (float)height - yOffset);
- rlVertex2f((float)posX + xOffset, (float)posY + (float)height - yOffset);
+ // right: top => bottom
+ rlVertex2f(x + w - o, y + o);
+ rlVertex2f(x + w - o, y + h - o);
- rlVertex2f((float)posX + xOffset, (float)posY + (float)height - yOffset);
- rlVertex2f((float)posX + xOffset, (float)posY + yOffset);
+ // bottom: right => left
+ rlVertex2f(x + w - o, y + h - o);
+ rlVertex2f(x + o, y + h - o);
+
+ // left: bottom => top
+ rlVertex2f(x + o, y + h - o);
+ rlVertex2f(x + o, y + o);
rlEnd();
/* test program
#include "raylib.h"
int main(void) {
SetConfigFlags(FLAG_VSYNC_HINT);
InitWindow(800, 800, "DrawRectangleLines bug");
Camera2D camera = {.zoom = 1};
bool growing = true;
while (!WindowShouldClose())
{
const float spike = GetFrameTime() * 0.5f;
// NOTE: uncomment line below to use animation
// camera.zoom = growing ? (camera.zoom + spike) : (camera.zoom - spike);
if (IsKeyPressed(KEY_SPACE))
camera.zoom = growing ? (camera.zoom + 1) : (camera.zoom - 1);
growing = (camera.zoom <= 1) ? true : (camera.zoom >= 7) ? false : growing;
BeginDrawing();
BeginMode2D(camera);
ClearBackground(BLACK);
DrawRectangleLines(50, 50, 50, 50, WHITE);
EndMode2D();
EndDrawing();
}
CloseWindow();
return 0;
} runtime logs
output of: `eglinfo -B`
|
With const float o = 0.51; // offset
There are other ways to expose what the exact deviation is. It may not matter except when multiplications are involved and when rounding, if any, occurs in casting values to int. PS: If at some point such a float is clipped into a short as a kind of union, it gets even weirder. |
The idea here was to just have something different than exact 0.5f to test how it would work. I tried 0.49, 0.51, 0.499, 0.501, and other bigger/smaller values. Float precision isn't really a problem here (I think). This is really just a problem with OpenGL itself not really being meant for such usage. Hitting perfect pixels with |
I think "deterministic" is the wrong term. They key thing is to know where in a certain "diamond" you must be hitting to light a particular pixel. Then there is the matter of stepping through pixels (as when drawing a line) to light the starting pixel, the ending pixel, and all between. That can definitely depend on how the arithmetic is done and with what precision of operations. It will be a great lesson to try the same thing manually though. Second-guessing OpenGL implementations is certainly challenging. You could draw a line yourself pixel-by-pixel to confirm what the challenges are, but that will still leave you stymied to figure out how to predict what OpenGL would do in drawing the same line as an internal operation. PS: To see what struggle is involved, you can investigate what PostScript and TeX go through to obtain precision and predictable graphics at very high DPI. |
Issue description
If you draw a rectangle outline using DrawRectangleLines(0, 0, w, h, WHITE) the lower right corner is missing.
Environment
N/A
Issue Screenshot
/
Code Example
The text was updated successfully, but these errors were encountered: