From cd2d14c0fde01382621f6f774264e3d9a38a0d9a Mon Sep 17 00:00:00 2001 From: Lennard Date: Mon, 4 Nov 2024 16:26:42 +0100 Subject: [PATCH] Fix blending for CameraOutputMode::Skip (#16157) # Objective Currently, if we have two cameras with the same output texture, one with `CameraOutputMode::Write` and one with `CameraOutputMode::Skip`, it is possible for the `CameraOutputMode::Write` camera to be assigned alpha blending (which is the fallback blending when multiple cameras write to the same output texture), although it is the only camera writing to the output texture. This may or may not happen every restart of the app, because the camera iteration order in prepare_view_upscaling_pipelines isn't consistent. Since this is random behaviour I consider this a bug and didn't add a migration guide. ## Solution In `prepare_view_upscaling_pipelines` make sure we don't consider cameras with CameraOutputMode::Skip to be outputting something to the output texture. ## Testing I ran a few examples to make sure nothing obvious is broken. There is no example using CameraOutputMode::Skip, so I only tested the change in my own App where this was relevant, which however isn't public. --- .../bevy_core_pipeline/src/upscaling/mod.rs | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/bevy_core_pipeline/src/upscaling/mod.rs b/crates/bevy_core_pipeline/src/upscaling/mod.rs index 42f6744bfb..b686d44849 100644 --- a/crates/bevy_core_pipeline/src/upscaling/mod.rs +++ b/crates/bevy_core_pipeline/src/upscaling/mod.rs @@ -46,28 +46,32 @@ fn prepare_view_upscaling_pipelines( let mut output_textures = HashSet::new(); for (entity, view_target, camera) in view_targets.iter() { let out_texture_id = view_target.out_texture().id(); - let blend_state = if let Some(ExtractedCamera { - output_mode: CameraOutputMode::Write { blend_state, .. }, - .. - }) = camera - { - match *blend_state { - None => { - // If we've already seen this output for a camera and it doesn't have a output blend - // mode configured, default to alpha blend so that we don't accidentally overwrite - // the output texture - if output_textures.contains(&out_texture_id) { - Some(BlendState::ALPHA_BLENDING) - } else { - None + let blend_state = if let Some(extracted_camera) = camera { + match extracted_camera.output_mode { + CameraOutputMode::Skip => None, + CameraOutputMode::Write { blend_state, .. } => { + let already_seen = output_textures.contains(&out_texture_id); + output_textures.insert(out_texture_id); + + match blend_state { + None => { + // If we've already seen this output for a camera and it doesn't have a output blend + // mode configured, default to alpha blend so that we don't accidentally overwrite + // the output texture + if already_seen { + Some(BlendState::ALPHA_BLENDING) + } else { + None + } + } + _ => blend_state, } } - _ => *blend_state, } } else { + output_textures.insert(out_texture_id); None }; - output_textures.insert(out_texture_id); let key = BlitPipelineKey { texture_format: view_target.out_texture_format(),