diff --git a/crates/bevy_camera/src/camera.rs b/crates/bevy_camera/src/camera.rs index a70cbeb39e..aaa85de27e 100644 --- a/crates/bevy_camera/src/camera.rs +++ b/crates/bevy_camera/src/camera.rs @@ -80,14 +80,20 @@ impl Viewport { } } - pub fn with_override( - &self, + pub fn from_viewport_and_override( + viewport: Option<&Self>, main_pass_resolution_override: Option<&MainPassResolutionOverride>, - ) -> Self { - let mut viewport = self.clone(); + ) -> Option { + let mut viewport = viewport.cloned(); + if let Some(override_size) = main_pass_resolution_override { - viewport.physical_size = **override_size; + if viewport.is_none() { + viewport = Some(Viewport::default()); + } + + viewport.as_mut().unwrap().physical_size = **override_size; } + viewport } } @@ -101,7 +107,7 @@ impl Viewport { /// * Insert this component on a 3d camera entity in the render world. /// * The resolution override must be smaller than the camera's viewport size. /// * The resolution override is specified in physical pixels. -#[derive(Component, Reflect, Deref)] +#[derive(Component, Reflect, Deref, Debug)] #[reflect(Component)] pub struct MainPassResolutionOverride(pub UVec2); diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index c5ee7a798d..0ee9144a95 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -2,6 +2,7 @@ use crate::{ core_3d::Opaque3d, skybox::{SkyboxBindGroup, SkyboxPipelineId}, }; +use bevy_camera::Viewport; use bevy_ecs::{prelude::World, query::QueryItem}; use bevy_render::{ camera::{ExtractedCamera, MainPassResolutionOverride}, @@ -91,8 +92,10 @@ impl ViewNode for MainOpaquePass3dNode { let mut render_pass = TrackedRenderPass::new(&render_device, render_pass); let pass_span = diagnostics.pass_span(&mut render_pass, "main_opaque_pass_3d"); - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); + if let Some(viewport) = + Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override) + { + render_pass.set_camera_viewport(&viewport); } // Opaque draws diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs index 393167227f..ec108b8753 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs @@ -1,5 +1,6 @@ use super::{Camera3d, ViewTransmissionTexture}; use crate::core_3d::Transmissive3d; +use bevy_camera::Viewport; use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_image::ToExtents; use bevy_render::{ @@ -110,8 +111,11 @@ impl ViewNode for MainTransmissivePass3dNode { let mut render_pass = render_context.begin_tracked_render_pass(render_pass_descriptor); - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); + if let Some(viewport) = Viewport::from_viewport_and_override( + camera.viewport.as_ref(), + resolution_override, + ) { + render_pass.set_camera_viewport(&viewport); } if let Err(err) = transmissive_phase.render(&mut render_pass, world, view_entity) { diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs index 0c70ec23a0..bbe14578b0 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs @@ -1,4 +1,5 @@ use crate::core_3d::Transparent3d; +use bevy_camera::Viewport; use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_render::{ camera::{ExtractedCamera, MainPassResolutionOverride}, @@ -69,8 +70,10 @@ impl ViewNode for MainTransparentPass3dNode { let pass_span = diagnostics.pass_span(&mut render_pass, "main_transparent_pass_3d"); - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); + if let Some(viewport) = + Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override) + { + render_pass.set_camera_viewport(&viewport); } if let Err(err) = transparent_phase.render(&mut render_pass, world, view_entity) { diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index ab87fccee6..dc65fa811d 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -1,3 +1,4 @@ +use bevy_camera::Viewport; use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_render::camera::MainPassResolutionOverride; use bevy_render::experimental::occlusion_culling::OcclusionCulling; @@ -221,8 +222,10 @@ fn run_deferred_prepass<'w>( occlusion_query_set: None, }); let mut render_pass = TrackedRenderPass::new(&render_device, render_pass); - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); + if let Some(viewport) = + Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override) + { + render_pass.set_camera_viewport(&viewport); } // Opaque draws diff --git a/crates/bevy_core_pipeline/src/oit/resolve/node.rs b/crates/bevy_core_pipeline/src/oit/resolve/node.rs index 77352e5ecb..83b8c604f4 100644 --- a/crates/bevy_core_pipeline/src/oit/resolve/node.rs +++ b/crates/bevy_core_pipeline/src/oit/resolve/node.rs @@ -1,3 +1,4 @@ +use bevy_camera::Viewport; use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_render::{ camera::{ExtractedCamera, MainPassResolutionOverride}, @@ -63,8 +64,10 @@ impl ViewNode for OitResolveNode { occlusion_query_set: None, }); - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); + if let Some(viewport) = + Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override) + { + render_pass.set_camera_viewport(&viewport); } render_pass.set_render_pipeline(pipeline); diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index c4cc7b1d55..1b54ee8c5d 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -1,3 +1,4 @@ +use bevy_camera::Viewport; use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_render::{ camera::{ExtractedCamera, MainPassResolutionOverride}, @@ -186,8 +187,10 @@ fn run_prepass<'w>( let mut render_pass = TrackedRenderPass::new(&render_device, render_pass); let pass_span = diagnostics.pass_span(&mut render_pass, label); - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); + if let Some(viewport) = + Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override) + { + render_pass.set_camera_viewport(&viewport); } // Opaque draws diff --git a/examples/shader/custom_render_phase.rs b/examples/shader/custom_render_phase.rs index 89f5ce6d67..3dffdf2ba5 100644 --- a/examples/shader/custom_render_phase.rs +++ b/examples/shader/custom_render_phase.rs @@ -12,6 +12,7 @@ use std::ops::Range; +use bevy::camera::Viewport; use bevy::pbr::SetMeshViewEmptyBindGroup; use bevy::{ core_pipeline::core_3d::graph::{Core3d, Node3d}, @@ -618,8 +619,10 @@ impl ViewNode for CustomDrawNode { occlusion_query_set: None, }); - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); + if let Some(viewport) = + Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override) + { + render_pass.set_camera_viewport(&viewport); } // Render the phase