You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
Canvases created with Canvas::with_window_size use the logical size of the
window, resulting in a blurry image when it is scaled up to the physical size of
the window.
Screenshots
Correct Image
Notice how the rectangle is crisp at the edge. This is what happens when I draw
the image directly to the screen, without using a Canvas.
Incorrect Image
Notice how the edges of the rectangle blur. This occurs because the Canvas is
scaled up from the logical size to the actual physical size of the screen. On my
machine, my HIDPI factor is 1.25, so this means the Canvas is scaled from 200x200
to 250x250, resulting in blurriness.
Below is a close up of the two images, showing the difference.
Expected behavior
I would expect the canvas given by with_window_size to be of the same size
as the phyiscal dimensions of the window, so that when it is draw to the screen,
the result is exactly as sharp as it would be if you were to just draw things
to the screen directly in the first place
To reproduce
// This code demonstrates the blurry version of the rectangle.// Comment out the lines with "comment this out" at the end to see the correct image.fndraw(&mutself,ctx:&mut ggez::Context) -> ggez::GameResult{// Let's draw a rectanglelet mesh = ggez::graphics::Mesh::new_rectangle(
ctx,
ggez::graphics::DrawMode::fill(),
ggez::graphics::Rect::new(25.0,25.0,50.0,100.0),
ggez::graphics::WHITE,)?;let canvas = ggez::graphics::Canvas::with_window_size(ctx).expect("Couldn't make canvas!");// Draw the rectangle in the canvas
ggez::graphics::set_canvas(ctx,Some(&canvas));// comment this out
ggez::graphics::draw(ctx,&mesh, ggez::graphics::DrawParam::default())?;// Now swap back to the screen and draw the canvas to the screen
ggez::graphics::set_canvas(ctx,None);// comment this out
ggez::graphics::draw(ctx,&canvas, ggez::graphics::DrawParam::default())?;
ggez::graphics::present(ctx)?;Ok(())}
Workarounds
It is possible to workaround this issue by scaling the Canvas up to the physical
size of the screen, and then scaling it back down before rendering. This is
frustrating though because the HIDPI factor lives in ggez:graphics::window() and
requires a bit of shuffling around to get it to work right.
// When we make our canvas, we first scale it up to the physical size of the windowlet window = graphics::window(ctx);let hidpi_factor = window.get_hidpi_factor();let physical_size = window.get_inner_size().unwrap().to_physical(hidpi_factor);let(width, height) = (physical_size.widthasu16, physical_size.heightasu16);let samples = ggez::conf::NumSamples::One;let canvas = ggez::graphics::Canvas::new(ctx, width, height, samples).expect("Couldn't make canvas!");// Now we do our rendering as before.
ggez::graphics::set_canvas(ctx,Some(&canvas));
ggez::graphics::draw(ctx,&mesh, ggez::graphics::DrawParam::default())?;// When we render the canvas to the screen, we now scale the canvas back down
ggez::graphics::set_canvas(ctx,None);let scaled = DrawParam::default().scale([1.0 / hidpi_factor,1.0 / hidpi_factor]);
ggez::graphics::draw(ctx,&canvas, ggez::graphics::DrawParam::default())?;
ggez::graphics::present(ctx)?;Ok(())}
Hardware and Software:
ggez version: 0.5.1
OS: Windows 10, Update 2004 (Version 10.0.19041 Build 19041)
Check this out on the devel branch please, it's been updated to use a newer version of winit that is much more explicit about logical vs. physical sizes.
I just checked on the current devel and the problem is still the same (though the workaround would need to be adapted since the API changed somewhat).
Glancing over this I think that the problem lies in drawable_size, which says that it returns the drawable size in pixels, while actually returning the logical inner window size.
EDIT: Fixing his might need caution, as drawable_size is used in many places and changing it could have dramatic consequences. Also, digging through the source a bit I'm somewhat confused, as it seems that the width and height of WindowMode are actually supposed to be physical and not logical? This confuses me because currently they're logical...
Making this design decision clear right now: All pixel coordinates in ggez should refer to physical pixels, not any silly nonsense that the windowing system lies to you about logical pixels. So if making drawable_size() return physical pixels breaks things, then those things are broken and also need fixed.
Describe the bug
Canvases created with
Canvas::with_window_size
use the logical size of thewindow, resulting in a blurry image when it is scaled up to the physical size of
the window.
Screenshots
Correct Image
Notice how the rectangle is crisp at the edge. This is what happens when I draw
the image directly to the screen, without using a Canvas.
Incorrect Image
Notice how the edges of the rectangle blur. This occurs because the Canvas is
scaled up from the logical size to the actual physical size of the screen. On my
machine, my HIDPI factor is 1.25, so this means the Canvas is scaled from 200x200
to 250x250, resulting in blurriness.
Below is a close up of the two images, showing the difference.
Expected behavior
I would expect the canvas given by
with_window_size
to be of the same sizeas the phyiscal dimensions of the window, so that when it is draw to the screen,
the result is exactly as sharp as it would be if you were to just draw things
to the screen directly in the first place
To reproduce
Workarounds
It is possible to workaround this issue by scaling the Canvas up to the physical
size of the screen, and then scaling it back down before rendering. This is
frustrating though because the HIDPI factor lives in
ggez:graphics::window()
andrequires a bit of shuffling around to get it to work right.
Hardware and Software:
The text was updated successfully, but these errors were encountered: