-
-
Notifications
You must be signed in to change notification settings - Fork 22.1k
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
Fix draw_rect #32657
Fix draw_rect #32657
Conversation
Changes look good. Can you check that the spec is the same for 2.1 and 3.3? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be good to write a comment to explain why 0.5
is being added to the values 🙂
p_rect.position + Point2(0, offset), | ||
p_rect.position + Size2(0, p_rect.size.height - offset), | ||
p_rect.position + Point2(p_rect.size.width, offset), | ||
p_rect.position + Size2(p_rect.size.width, p_rect.size.height - offset), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The order used to be "add Point2
then add Size2
, but now it's no longer consistent, you have Point2
/Size2
here, but Size2
/Point2
for the next two calls.
It's the same typedef so it doesn't matter so much, but the inconsistency looks weird.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Size2 for all probably makes more sense semantically.
The idea of diamond exit is explained here: https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage-rules. (This is for directx, but it should be the same in OpenGL.)To make sure that the first pixel of a line is drawn, it should start at the x in the center(0.5, 0.5) of the pixel area. If we start to draw at the top left(0,0), the line might never cut the diamond pattern of the first pixel, leaving a gap at the corner. This works fine on my nvidia GPU, but on my integrated intel haswell gpu it doesn't(At least the missing pixel is now consistently at the top right). I don't think it's possible to create cross platform pixel perfect lines with OpenGL. The algorithm is in the specification for OpenGL 2.1 and 3.3, but vendors are allowed to use slightly different algorithms. It might be interesting if someone with a AMD GPU or more modern intel GPU could test this. |
More resources here, explained pretty succinctly. http://graphics-software-engineer.blogspot.com/2012/04/rasterization-rules.html |
Changes seem good to me, but I agree that adding a short comment in both GLES2 and GLES3 before the |
OpenGL uses the diamond exit rule to rasterize lines. If we don't shift the points down and to the right by 0.5, the line can sometimes miss a pixel when it shouldn't. The final fragment of a line isn't drawn. By drawing the lines clockwise, we can avoid a missing pixel in the rectangle. See section 3.4.1 in the OpenGL 1.5 specification. Fixes godotengine#32279
Thanks! |
Can't reproduce with your code. Would be helpful if you could add a minimal reproduction project. |
Can you try to scale the Control by 16,16 this is what I do in my case |
I understand why this was added, but this is not the right way and it will likely need to be reverted. The reason is that lines can be used with a canvas scale and this will break them. Researching a better solution is probably a better idea, or likely attempting to implement it in 4.0, which supplies the separate canvas matrices. |
I suggest doing the pixel shifting at matrix level instead for lines. |
As discussed in godotengine#32657, this can't be done here as lines can be used with a canvas scale, and this breaks them. A suggestion is to do the pixel shifting at matrix level instead. Fixes godotengine#33393. Fixes godotengine#33421.
Partial revert of #32657, undoing line shifting by 0.5
As discussed in godotengine#32657, this can't be done here as lines can be used with a canvas scale, and this breaks them. A suggestion is to do the pixel shifting at matrix level instead. Fixes godotengine#33393. Fixes godotengine#33421.
OpenGL uses the diamond exit rule to rasterize lines. If we don't shift
the points down and to the right by 0.5, the line can sometimes miss a
pixel when it shouldn't. The final fragment of a line isn't drawn. By
drawing the lines clockwise, we can avoid a missing pixel in the rectangle.
See section 3.4.1 in the OpenGL 1.5 specification.
Fixes #32279