update camera projection if viewport changed (#5945)

fixes https://github.com/bevyengine/bevy/issues/5944

Uses the second solution:
> 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).
This commit is contained in:
Jakob Hellermann 2022-10-28 19:56:31 +00:00
parent fe7ebd4326
commit 0401f04ba9

View File

@ -13,9 +13,8 @@ use bevy_ecs::{
component::Component, component::Component,
entity::Entity, entity::Entity,
event::EventReader, event::EventReader,
query::Added,
reflect::ReflectComponent, reflect::ReflectComponent,
system::{Commands, ParamSet, Query, Res}, system::{Commands, Query, Res},
}; };
use bevy_math::{Mat4, Ray, UVec2, UVec4, Vec2, Vec3}; use bevy_math::{Mat4, Ray, UVec2, UVec4, Vec2, Vec3};
use bevy_reflect::prelude::*; use bevy_reflect::prelude::*;
@ -68,6 +67,8 @@ pub struct RenderTargetInfo {
pub struct ComputedCameraValues { pub struct ComputedCameraValues {
projection_matrix: Mat4, projection_matrix: Mat4,
target_info: Option<RenderTargetInfo>, target_info: Option<RenderTargetInfo>,
// position and size of the `Viewport`
old_viewport_size: Option<UVec2>,
} }
/// The defining component for camera entities, storing information about how and what to render /// The defining component for camera entities, storing information about how and what to render
@ -404,10 +405,7 @@ pub fn camera_system<T: CameraProjection + Component>(
mut image_asset_events: EventReader<AssetEvent<Image>>, mut image_asset_events: EventReader<AssetEvent<Image>>,
windows: Res<Windows>, windows: Res<Windows>,
images: Res<Assets<Image>>, images: Res<Assets<Image>>,
mut queries: ParamSet<( mut cameras: Query<(&mut Camera, &mut T)>,
Query<(Entity, &mut Camera, &mut T)>,
Query<Entity, Added<Camera>>,
)>,
) { ) {
let mut changed_window_ids = Vec::new(); let mut changed_window_ids = Vec::new();
@ -440,18 +438,21 @@ pub fn camera_system<T: CameraProjection + Component>(
}) })
.collect(); .collect();
let mut added_cameras = vec![]; for (mut camera, mut camera_projection) in &mut cameras {
for entity in &queries.p1() { let viewport_size = camera
added_cameras.push(entity); .viewport
} .as_ref()
for (entity, mut camera, mut camera_projection) in &mut queries.p0() { .map(|viewport| viewport.physical_size);
if camera if camera
.target .target
.is_changed(&changed_window_ids, &changed_image_handles) .is_changed(&changed_window_ids, &changed_image_handles)
|| added_cameras.contains(&entity) || camera.is_added()
|| camera_projection.is_changed() || camera_projection.is_changed()
|| camera.computed.old_viewport_size != viewport_size
{ {
camera.computed.target_info = camera.target.get_render_target_info(&windows, &images); camera.computed.target_info = camera.target.get_render_target_info(&windows, &images);
camera.computed.old_viewport_size = viewport_size;
if let Some(size) = camera.logical_viewport_size() { if let Some(size) = camera.logical_viewport_size() {
camera_projection.update(size.x, size.y); camera_projection.update(size.x, size.y);
camera.computed.projection_matrix = camera_projection.get_projection_matrix(); camera.computed.projection_matrix = camera_projection.get_projection_matrix();