Fix draw rectangle in BufferedDrawNode not being aligned with framebuffer rectangle
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
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.
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)
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.