From 56cfc6d8b9aea81d4cb4f10d75e4001a30fff8c9 Mon Sep 17 00:00:00 2001 From: robtfm <50659922+robtfm@users.noreply.github.com> Date: Tue, 17 Jan 2023 17:39:28 +0000 Subject: [PATCH] fix bloom viewport (#6802) # Objective fix bloom when used on a camera with a viewport specified ## Solution - pass viewport into the prefilter shader, and use it to read from the correct section of the original rendered screen - don't apply viewport for the intermediate bloom passes, only for the final blend output --- .../bevy_core_pipeline/src/bloom/bloom.wgsl | 6 ++-- crates/bevy_core_pipeline/src/bloom/mod.rs | 29 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/crates/bevy_core_pipeline/src/bloom/bloom.wgsl b/crates/bevy_core_pipeline/src/bloom/bloom.wgsl index 0e6addeef3ee3..a6bab621db520 100644 --- a/crates/bevy_core_pipeline/src/bloom/bloom.wgsl +++ b/crates/bevy_core_pipeline/src/bloom/bloom.wgsl @@ -5,6 +5,7 @@ struct BloomUniforms { knee: f32, scale: f32, intensity: f32, + viewport: vec4, }; @group(0) @binding(0) @@ -87,7 +88,8 @@ fn sample_original_3x3_tent(uv: vec2, scale: vec2) -> vec4 { } @fragment -fn downsample_prefilter(@location(0) uv: vec2) -> @location(0) vec4 { +fn downsample_prefilter(@location(0) output_uv: vec2) -> @location(0) vec4 { + let sample_uv = uniforms.viewport.xy + output_uv * uniforms.viewport.zw; let texel_size = 1.0 / vec2(textureDimensions(original)); let scale = texel_size; @@ -98,7 +100,7 @@ fn downsample_prefilter(@location(0) uv: vec2) -> @location(0) vec4 { 0.25 / uniforms.knee, ); - var o: vec4 = sample_13_tap(uv, scale); + var o: vec4 = sample_13_tap(sample_uv, scale); o = quadratic_threshold(o, uniforms.threshold, curve); o = max(o, vec4(0.00001)); diff --git a/crates/bevy_core_pipeline/src/bloom/mod.rs b/crates/bevy_core_pipeline/src/bloom/mod.rs index 3ceb6a2645581..ad438b2a25dcf 100644 --- a/crates/bevy_core_pipeline/src/bloom/mod.rs +++ b/crates/bevy_core_pipeline/src/bloom/mod.rs @@ -7,7 +7,7 @@ use bevy_ecs::{ system::{Commands, Query, Res, ResMut, Resource}, world::{FromWorld, World}, }; -use bevy_math::UVec2; +use bevy_math::{UVec2, UVec4, Vec4}; use bevy_reflect::{Reflect, TypeUuid}; use bevy_render::{ camera::ExtractedCamera, @@ -152,18 +152,27 @@ impl ExtractComponent for BloomSettings { return None; } - camera.physical_viewport_size().map(|size| { + if let (Some((origin, _)), Some(size), Some(target_size)) = ( + camera.physical_viewport_rect(), + camera.physical_viewport_size(), + camera.physical_target_size(), + ) { let min_view = size.x.min(size.y) / 2; let mip_count = calculate_mip_count(min_view); let scale = (min_view / 2u32.pow(mip_count)) as f32 / 8.0; - BloomUniform { + Some(BloomUniform { threshold: settings.threshold, knee: settings.knee, scale: settings.scale * scale, intensity: settings.intensity, - } - }) + viewport: UVec4::new(origin.x, origin.y, size.x, size.y).as_vec4() + / UVec4::new(target_size.x, target_size.y, target_size.x, target_size.y) + .as_vec4(), + }) + } else { + None + } } } @@ -246,9 +255,6 @@ impl Node for BloomNode { &bind_groups.prefilter_bind_group, &[uniform_index.index()], ); - if let Some(viewport) = camera.viewport.as_ref() { - prefilter_pass.set_camera_viewport(viewport); - } prefilter_pass.draw(0..3, 0..1); } @@ -270,9 +276,6 @@ impl Node for BloomNode { &bind_groups.downsampling_bind_groups[mip as usize - 1], &[uniform_index.index()], ); - if let Some(viewport) = camera.viewport.as_ref() { - downsampling_pass.set_camera_viewport(viewport); - } downsampling_pass.draw(0..3, 0..1); } @@ -294,9 +297,6 @@ impl Node for BloomNode { &bind_groups.upsampling_bind_groups[mip as usize - 1], &[uniform_index.index()], ); - if let Some(viewport) = camera.viewport.as_ref() { - upsampling_pass.set_camera_viewport(viewport); - } upsampling_pass.draw(0..3, 0..1); } @@ -612,6 +612,7 @@ pub struct BloomUniform { knee: f32, scale: f32, intensity: f32, + viewport: Vec4, } #[derive(Component)]