Fix resolution override to work even if the camera lacks a viewport

This commit is contained in:
JMS55 2025-07-07 22:27:11 -04:00
parent 1b714636ab
commit 10c96e8301
8 changed files with 48 additions and 20 deletions

View File

@ -80,14 +80,20 @@ impl Viewport {
} }
} }
pub fn with_override( pub fn from_viewport_and_override(
&self, viewport: Option<&Self>,
main_pass_resolution_override: Option<&MainPassResolutionOverride>, main_pass_resolution_override: Option<&MainPassResolutionOverride>,
) -> Self { ) -> Option<Self> {
let mut viewport = self.clone(); let mut viewport = viewport.cloned();
if let Some(override_size) = main_pass_resolution_override { 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 viewport
} }
} }
@ -101,7 +107,7 @@ impl Viewport {
/// * Insert this component on a 3d camera entity in the render world. /// * 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 must be smaller than the camera's viewport size.
/// * The resolution override is specified in physical pixels. /// * The resolution override is specified in physical pixels.
#[derive(Component, Reflect, Deref)] #[derive(Component, Reflect, Deref, Debug)]
#[reflect(Component)] #[reflect(Component)]
pub struct MainPassResolutionOverride(pub UVec2); pub struct MainPassResolutionOverride(pub UVec2);

View File

@ -2,6 +2,7 @@ use crate::{
core_3d::Opaque3d, core_3d::Opaque3d,
skybox::{SkyboxBindGroup, SkyboxPipelineId}, skybox::{SkyboxBindGroup, SkyboxPipelineId},
}; };
use bevy_camera::Viewport;
use bevy_ecs::{prelude::World, query::QueryItem}; use bevy_ecs::{prelude::World, query::QueryItem};
use bevy_render::{ use bevy_render::{
camera::{ExtractedCamera, MainPassResolutionOverride}, camera::{ExtractedCamera, MainPassResolutionOverride},
@ -91,8 +92,10 @@ impl ViewNode for MainOpaquePass3dNode {
let mut render_pass = TrackedRenderPass::new(&render_device, render_pass); let mut render_pass = TrackedRenderPass::new(&render_device, render_pass);
let pass_span = diagnostics.pass_span(&mut render_pass, "main_opaque_pass_3d"); let pass_span = diagnostics.pass_span(&mut render_pass, "main_opaque_pass_3d");
if let Some(viewport) = camera.viewport.as_ref() { if let Some(viewport) =
render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
{
render_pass.set_camera_viewport(&viewport);
} }
// Opaque draws // Opaque draws

View File

@ -1,5 +1,6 @@
use super::{Camera3d, ViewTransmissionTexture}; use super::{Camera3d, ViewTransmissionTexture};
use crate::core_3d::Transmissive3d; use crate::core_3d::Transmissive3d;
use bevy_camera::Viewport;
use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_image::ToExtents; use bevy_image::ToExtents;
use bevy_render::{ use bevy_render::{
@ -110,8 +111,11 @@ impl ViewNode for MainTransmissivePass3dNode {
let mut render_pass = let mut render_pass =
render_context.begin_tracked_render_pass(render_pass_descriptor); render_context.begin_tracked_render_pass(render_pass_descriptor);
if let Some(viewport) = camera.viewport.as_ref() { if let Some(viewport) = Viewport::from_viewport_and_override(
render_pass.set_camera_viewport(&viewport.with_override(resolution_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) { if let Err(err) = transmissive_phase.render(&mut render_pass, world, view_entity) {

View File

@ -1,4 +1,5 @@
use crate::core_3d::Transparent3d; use crate::core_3d::Transparent3d;
use bevy_camera::Viewport;
use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_render::{ use bevy_render::{
camera::{ExtractedCamera, MainPassResolutionOverride}, camera::{ExtractedCamera, MainPassResolutionOverride},
@ -69,8 +70,10 @@ impl ViewNode for MainTransparentPass3dNode {
let pass_span = diagnostics.pass_span(&mut render_pass, "main_transparent_pass_3d"); let pass_span = diagnostics.pass_span(&mut render_pass, "main_transparent_pass_3d");
if let Some(viewport) = camera.viewport.as_ref() { if let Some(viewport) =
render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); 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) { if let Err(err) = transparent_phase.render(&mut render_pass, world, view_entity) {

View File

@ -1,3 +1,4 @@
use bevy_camera::Viewport;
use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_render::camera::MainPassResolutionOverride; use bevy_render::camera::MainPassResolutionOverride;
use bevy_render::experimental::occlusion_culling::OcclusionCulling; use bevy_render::experimental::occlusion_culling::OcclusionCulling;
@ -221,8 +222,10 @@ fn run_deferred_prepass<'w>(
occlusion_query_set: None, occlusion_query_set: None,
}); });
let mut render_pass = TrackedRenderPass::new(&render_device, render_pass); let mut render_pass = TrackedRenderPass::new(&render_device, render_pass);
if let Some(viewport) = camera.viewport.as_ref() { if let Some(viewport) =
render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
{
render_pass.set_camera_viewport(&viewport);
} }
// Opaque draws // Opaque draws

View File

@ -1,3 +1,4 @@
use bevy_camera::Viewport;
use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_render::{ use bevy_render::{
camera::{ExtractedCamera, MainPassResolutionOverride}, camera::{ExtractedCamera, MainPassResolutionOverride},
@ -63,8 +64,10 @@ impl ViewNode for OitResolveNode {
occlusion_query_set: None, occlusion_query_set: None,
}); });
if let Some(viewport) = camera.viewport.as_ref() { if let Some(viewport) =
render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
{
render_pass.set_camera_viewport(&viewport);
} }
render_pass.set_render_pipeline(pipeline); render_pass.set_render_pipeline(pipeline);

View File

@ -1,3 +1,4 @@
use bevy_camera::Viewport;
use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_render::{ use bevy_render::{
camera::{ExtractedCamera, MainPassResolutionOverride}, camera::{ExtractedCamera, MainPassResolutionOverride},
@ -186,8 +187,10 @@ fn run_prepass<'w>(
let mut render_pass = TrackedRenderPass::new(&render_device, render_pass); let mut render_pass = TrackedRenderPass::new(&render_device, render_pass);
let pass_span = diagnostics.pass_span(&mut render_pass, label); let pass_span = diagnostics.pass_span(&mut render_pass, label);
if let Some(viewport) = camera.viewport.as_ref() { if let Some(viewport) =
render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
{
render_pass.set_camera_viewport(&viewport);
} }
// Opaque draws // Opaque draws

View File

@ -12,6 +12,7 @@
use std::ops::Range; use std::ops::Range;
use bevy::camera::Viewport;
use bevy::pbr::SetMeshViewEmptyBindGroup; use bevy::pbr::SetMeshViewEmptyBindGroup;
use bevy::{ use bevy::{
core_pipeline::core_3d::graph::{Core3d, Node3d}, core_pipeline::core_3d::graph::{Core3d, Node3d},
@ -618,8 +619,10 @@ impl ViewNode for CustomDrawNode {
occlusion_query_set: None, occlusion_query_set: None,
}); });
if let Some(viewport) = camera.viewport.as_ref() { if let Some(viewport) =
render_pass.set_camera_viewport(&viewport.with_override(resolution_override)); Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
{
render_pass.set_camera_viewport(&viewport);
} }
// Render the phase // Render the phase