Closed
Description
Describe the bug
I'm basically having the same problem as #635 – I'm trying to draw stuff to a smaller canvas, then draw that canvas scaled up on the main canvas in order to achieve a crisp pixel-art effect.
To Reproduce
Here is how I'm setting up the Canvas
objects, including setting their samplers:
let mut main_canvas = Canvas::from_frame(ctx, Color::BLACK);
main_canvas.set_sampler(Sampler::nearest_clamp());
let mut sub_image = ScreenImage::new(ctx, None, 1.0 / SCREEN_SCALE, 1.0 / SCREEN_SCALE, 1);
let mut sub_canvas = Canvas::from_screen_image(ctx, &mut sub_image, Color::BLACK);
sub_canvas.set_sampler(Sampler::nearest_clamp());
// Draw stuff...
sub_canvas.finish(ctx)?;
let image = sub_image.image(ctx);
main_canvas.draw(&image, DrawParam::new().scale(glam::vec2(SCREEN_SCALE, SCREEN_SCALE)));
main_canvas.finish(ctx)?;
Expected behavior
A scaled-up canvas to render with nearest-neighbour filtering.
Screenshots or pasted code
This is instead what is produced:
You can see the edges are significantly blurred.
Here's the source code that produced that image. Dead simple, just draws a rect to the smaller canvas, then draws that to the main canvas.
use std::f32::consts::TAU;
use ggez::{graphics::*, *};
const GAME_SIZE: (f32, f32) = (240.0, 180.0);
const SCREEN_SCALE: f32 = 8.0;
struct MainState {}
impl event::EventHandler<ggez::GameError> for MainState {
fn update(&mut self, _ctx: &mut Context) -> GameResult {
Ok(())
}
fn draw(&mut self, ctx: &mut Context) -> GameResult {
let mut main_canvas = Canvas::from_frame(ctx, Color::BLACK);
main_canvas.set_sampler(Sampler::nearest_clamp());
let mut sub_image = ScreenImage::new(ctx, None, 1.0 / SCREEN_SCALE, 1.0 / SCREEN_SCALE, 1);
let mut sub_canvas = Canvas::from_screen_image(ctx, &mut sub_image, Color::BLACK);
sub_canvas.set_sampler(Sampler::nearest_clamp());
let rect = Rect::new(55.0, 40.0, 100.0, 50.0);
sub_canvas.draw(
&Quad,
DrawParam::new()
.dest(rect.point())
.scale(rect.size())
.color(Color::WHITE)
.rotation(TAU / 16.0),
);
sub_canvas.finish(ctx)?;
let image = sub_image.image(ctx);
main_canvas.draw(&image, DrawParam::new().scale(glam::vec2(SCREEN_SCALE, SCREEN_SCALE)));
main_canvas.finish(ctx)?;
Ok(())
}
}
pub fn main() -> GameResult {
let cb = ggez::ContextBuilder::new("foo", "bar").window_mode(
ggez::conf::WindowMode::default().dimensions(GAME_SIZE.0 * SCREEN_SCALE, GAME_SIZE.1 * SCREEN_SCALE),
);
let (ctx, event_loop) = cb.build()?;
let state = MainState {};
event::run(ctx, event_loop, state)
}
Hardware and Software:
- ggez version: 0.8.1
- OS: MacOS 12.5
- Graphics card: Apple M1 Max