bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Changing the `Viewport` of a camera doesn't update its projection

Open jakobhellermann opened this issue 3 years ago • 0 comments

Bevy version

main (6f2cc0b30e335f3084f7028498c0866279c78099

What you did

    cam.viewport = Some(Viewport {
        physical_position: UVec2::new(viewport_pos.x as u32, viewport_pos.y as u32),
        physical_size: UVec2::new(viewport_size.x as u32, viewport_size.y as u32),
        depth: 0.0..1.0,
    });

What went wrong

The projection of the camera got messed up.

Why does this happen?

The Camera maintains some computed values, like the projection matrix Mat4 and the render target size. This computed info is only updated if 1. the render target changed, 2. the camera got added or 3. the camera projection got changed. Changing the viewport also changed the projection which isn't caught here.

https://github.com/bevyengine/bevy/blob/6f2cc0b30e335f3084f7028498c0866279c78099/crates/bevy_render/src/camera/camera.rs#L380-L392

How to solve this

I can think of two solutions.

  1. we add || camera.is_changed(), relying on change detection. This is overly sensitive as this would also return true if someone changed is_active or priority, or if someone mistakenly had a unused deref_mut somewhere.
  2. keep track of the old viewport in the computed_state, and if camera.viewport != camera.computed_state.old_viewport, then update the projection. This is more reliable, but needs to store two UVec2s more in the camera (probably not a big deal).

jakobhellermann avatar Sep 11 '22 08:09 jakobhellermann