Camera2D.render_target is upside-down
The render_target field of a Camera2D is upside-down. I have included a repro--the gist is that if you draw a texture to a render_target and then draw that render_target to the screen the texture appears upside-down.
use macroquad::prelude::*;
#[macroquad::main("Texture")]
async fn main() {
let mut render_target_camera = Camera2D::from_display_rect(Rect::new(0., 0., 800., 600.));
render_target_camera.render_target = Some(render_target(800, 600));
let ferris_texture: Texture2D = load_texture("examples/ferris.png").await;
loop {
// draw Ferris to the render_target texture
set_camera(render_target_camera);
clear_background(RED);
draw_texture(
ferris_texture,
0.,
0.,
WHITE,
);
// draw the render_target texture to the screen
set_camera(Camera2D::from_display_rect(Rect::new(0., 0., 800., 600.)));
draw_texture(
render_target_camera.render_target.unwrap().texture,
0.,
0.,
WHITE,
);
next_frame().await
}
}

I have the same issue in macroquad version 0.3.0-alpha.15.
For now I am using:
draw_texture_ex(
TEXTURE,
0.0,
0.0,
WHITE,
DrawTextureParams {
flip_y: true,
..Default::default()
},
);
As a temporary solution works.
The behavior depends on whether there's a render target or not.
use macroquad::prelude::*;
#[macroquad::main("Camera bug")]
async fn main() {
let render_target = render_target(600, 400);
let rect = Rect::new(0.0, 0.0, 600.0, 400.0);
let mut camera = Camera2D::from_display_rect(rect);
//camera.zoom.y = -camera.zoom.y; // uncomment this to fix
camera.render_target = Some(render_target); // or comment out this to fix
loop {
set_camera(&camera);
clear_background(BLANK);
draw_text("test", 50.0, 50.0, 32.0, GREEN);
draw_line(0.0, 0.0, 300.0, 300.0, 1.0, GREEN);
set_default_camera();
draw_texture(render_target.texture, 0.0, 0.0, WHITE);
next_frame().await
}
}
When using a camera without a render_target set, from_display_rect works correctly. When there is a render target, however, it needs to be flipped (either when rendering it to screen or when setting up the camera).
I thought the culprit is the minus sign in zoom: vec2(1. / rect.w * 2., -1. / rect.h * 2.), in Camera2D::from_display_rect but and reported it on Discord but was dismissed - i didn't know at the time it only happened when using a render target. It seems the fix needs to be somewhere else because removing the minus sign would break rendering to screen directly.
This is definitely an issue, but yeah you can just work around it :)
I have experienced the same issue but you can just set the camera rotation to 180 degrees (or +180 degrees if you want to rotate it around in the game)
The problem here - there are way too many projects already that have this scale: vec2(1, -1)(or flip_y: true) in their cameras.
So we are waiting for the fix for some major macroquad update, to break all the things altogether.
@not-fl3 That makes sense
I just runned the OP code in macroquad 0.4
use macroquad::prelude::*;
#[macroquad::test]
async fn test_camera_y() {
let mut render_target_camera = Camera2D::from_display_rect(Rect::new(0., 0., 800., 600.));
render_target_camera.render_target = Some(render_target(800, 600));
let ferris_texture = load_texture("examples/ferris.png").await.unwrap();
for _ in 0..100 {
// draw Ferris to the render_target texture
set_camera(&render_target_camera);
clear_background(RED);
draw_texture(&ferris_texture, 0., 0., WHITE);
// draw the render_target texture to the screen
set_camera(&Camera2D::from_display_rect(Rect::new(0., 0., 800., 600.)));
draw_texture(
&render_target_camera.render_target.as_ref().unwrap().texture,
0.,
0.,
WHITE,
);
next_frame().await
}
}
and the ferris is not upside down:
But there are reports on discord that the issue still persists? If someone knows how I can reproduce it in 0.4 - please, post it here :)
This works for me with 0.4.1 on a Mac.
It looks like it's flipped when using set_default_camera() though.
use macroquad::prelude::*;
#[macroquad::main("Test")]
async fn main() {
let mut render_target_camera = Camera2D::from_display_rect(Rect::new(0., 0., 800., 600.));
render_target_camera.render_target = Some(render_target(800, 600));
let ferris_texture = load_texture("ferris.png").await.unwrap();
for _ in 0..100 {
// draw Ferris to the render_target texture
set_camera(&render_target_camera);
clear_background(RED);
draw_texture(&ferris_texture, 0., 0., WHITE);
// draw the render_target texture to the screen
//set_camera(&Camera2D::from_display_rect(Rect::new(0., 0., 800., 600.)));
set_default_camera();
draw_texture(
&render_target_camera.render_target.as_ref().unwrap().texture,
0.,
0.,
WHITE,
);
next_frame().await
}
}
Confirming that the issue still happens in ollej's example using set_default_camera but not in not-fl3's example with set_camera.
I have just updated my project from 0.3.24 to 0.4.5 and ran into this. The y-axis of my program has been reversed.
Here is a minimal example:
use macroquad::prelude::*;
#[macroquad::main("example")]
async fn main() {
let camera = Camera2D {
target: vec2(0.0, 0.0),
zoom: vec2(1.0 / screen_width() * 2., -1.0 / screen_height() * 2.),
offset: vec2(0., 0.),
rotation: 0.,
render_target: None,
viewport: None,
};
let top_left = camera.screen_to_world(vec2(0.0, 0.0));
println!("top left: {:?}", top_left);
}
# 0.3.24
top left: Vec2(-400.0, -300.0)
# 0.4.5
top left: Vec2(-400.0, 300.0)
I have just updated my project from 0.3.24 to 0.4.5 and ran into this. The y-axis of my program has been reversed.
Here is a minimal example:
use macroquad::prelude::*; #[macroquad::main("example")] async fn main() { let camera = Camera2D { target: vec2(0.0, 0.0), zoom: vec2(1.0 / screen_width() * 2., -1.0 / screen_height() * 2.), offset: vec2(0., 0.), rotation: 0., render_target: None, viewport: None, }; let top_left = camera.screen_to_world(vec2(0.0, 0.0)); println!("top left: {:?}", top_left); }# 0.3.24 top left: Vec2(-400.0, -300.0) # 0.4.5 top left: Vec2(-400.0, 300.0)
Ha, I too performed the same upgrade and ended up experiencing the same change not long ago!
It's extra funky because I'm using Camera2D for some render target stuff as well and it seems like just flipping it everywhere doesn't do quite the right thing, for example here: https://github.com/profan/some-macroquad-things/blob/master/territory/src/main.rs
I have my own Camera2DExt::from_display_rect_fixed but use the normal old from_display_rect for my render target case, so I wonder what caused this upstream?
I have my own Camera2DExt::from_display_rect_fixed but use the normal old from_display_rect for my render target case, so I wonder what caused this upstream?
I'd guess the relevant change was https://github.com/not-fl3/macroquad/commit/38879533526259ead802a56f41dcfef78c273452, as it flips the zoom only for from_display_rect while leaving the default unflipped.
Also just ran into this by accident, playing around with the camera for the first time.
Reminds me of how we broke source rects in draw params between versions back then in ggez. Good times.
EDIT: I also just stumbled over these lines in the matrix function for Camera2D: https://github.com/not-fl3/macroquad/blob/4e27d18a207a55c00e486472ec88a88c63d6e961/src/camera.rs#L96-L100 What they do seems to fit the definition of turning everything upside down if there's a render_target ^^