osu-framework icon indicating copy to clipboard operation
osu-framework copied to clipboard

Fix draw rectangle in BufferedDrawNode not being aligned with framebuffer rectangle

Open minetoblend opened this issue 1 month ago • 3 comments

BufferedDrawNode rounds the frameBufferSize to int, but uses the original draw rectangle to do futher rendering with. This caused the content being misaligned with the pixel grid when the containers bounds weren't integer coordinates.

With pixelSnapping: false this would cause the content to become blurry due to the framebuffer texture being drawn with linear interpolation. A common workaround in osu for this is to use a FrameBufferScale greater than 1. With pixelSnapping: true this would instead result in the content randomly shifting around when the container changes position/size.

With this change it will first compute the frameBuffer size and base the draw rectangle off of that. At frameBufferScale=1 there should be no discernible difference between having the content in/outside a BufferedContainer, with both pixelSnapping being on or off.

Before

https://github.com/user-attachments/assets/a557cc86-1588-4b94-97fc-6d10dbb8e044

After

https://github.com/user-attachments/assets/cff12b01-e78b-41b6-9bed-a8524ac8fdec

Was briefly discussed on discord

minetoblend avatar Nov 17 '25 04:11 minetoblend

Maybe I'm just unsure of what I'm looking at, but it's still looking weird at low speed/0.25 scale (on my MBP as this is resolution dependent).

Before:

https://github.com/user-attachments/assets/b17aad58-a160-43e6-b95d-b9a38fc19b40

After:

https://github.com/user-attachments/assets/70b9ab43-b5d6-41ea-b498-5a425ca10744

The before one is behaving more like what I'd expect here where the box is centred but not aligned to the pixel grid, same with the diagonal lines being more stable.

smoogipoo avatar Nov 17 '25 05:11 smoogipoo

Maybe I'm just unsure of what I'm looking at, but it's still looking weird at low speed/0.25 scale

I'm honestly not 100% sure what it should look like at lower framebuffer scale either. I did some logging for how the draw rect is projected to the framebuffer viewport and aside from the floating point precision errors it looks like it's putting them exactly in the corners so I'm a bit puzzled about what causes the textures to behave this way.

renderer.PushOrtho(screenSpaceDrawRectangle);

var topLeft = new Vector4(DrawRectangle.Left, DrawRectangle.Top, 0, 1) * renderer.ProjectionMatrix;
var bottomRight = new Vector4(DrawRectangle.Right, DrawRectangle.Bottom, 0, 1) * renderer.ProjectionMatrix;

Logger.Log($"{topLeft.Xy}, {bottomRight.Xy}");
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1,0000002), (1,000001, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1,0000002), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1,000001, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1,000001, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1,000001, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1,0000002), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1,000001, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1,0000002), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1,0000002), (1,000001, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1,000001, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1,000001, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1,0000002), (1, -0,99999976)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:53 [verbose]: (-1, 1), (1, -0,99999976)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1,0000002), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1,0000002), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1,0000002), (1,000001, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1,0000002), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1,0000002), (1, -1)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -1,0000002)
[runtime] 2025-11-17 05:52:54 [verbose]: (-1, 1), (1, -0,99999976)

minetoblend avatar Nov 17 '25 05:11 minetoblend

Right... Looks like while the draw rect is rounded to whole pixels now, the drawbles are still drawn at their original coords which just moved the misaligned somewhere else. iirc pixi.js also let's you use a custom resolution for screen space effects so I'll try to look at what it does in the Adams scenario cuz I don't remember seeing that behavior there.

minetoblend avatar Nov 17 '25 07:11 minetoblend