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
This commit is contained in:
parent
1cc663f290
commit
45dfa71e03
@ -5,6 +5,7 @@ struct BloomUniforms {
|
|||||||
knee: f32,
|
knee: f32,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
intensity: f32,
|
intensity: f32,
|
||||||
|
viewport: vec4<f32>,
|
||||||
};
|
};
|
||||||
|
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
@ -87,7 +88,8 @@ fn sample_original_3x3_tent(uv: vec2<f32>, scale: vec2<f32>) -> vec4<f32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn downsample_prefilter(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> {
|
fn downsample_prefilter(@location(0) output_uv: vec2<f32>) -> @location(0) vec4<f32> {
|
||||||
|
let sample_uv = uniforms.viewport.xy + output_uv * uniforms.viewport.zw;
|
||||||
let texel_size = 1.0 / vec2<f32>(textureDimensions(original));
|
let texel_size = 1.0 / vec2<f32>(textureDimensions(original));
|
||||||
|
|
||||||
let scale = texel_size;
|
let scale = texel_size;
|
||||||
@ -98,7 +100,7 @@ fn downsample_prefilter(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> {
|
|||||||
0.25 / uniforms.knee,
|
0.25 / uniforms.knee,
|
||||||
);
|
);
|
||||||
|
|
||||||
var o: vec4<f32> = sample_13_tap(uv, scale);
|
var o: vec4<f32> = sample_13_tap(sample_uv, scale);
|
||||||
|
|
||||||
o = quadratic_threshold(o, uniforms.threshold, curve);
|
o = quadratic_threshold(o, uniforms.threshold, curve);
|
||||||
o = max(o, vec4<f32>(0.00001));
|
o = max(o, vec4<f32>(0.00001));
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use bevy_ecs::{
|
|||||||
system::{Commands, Query, Res, ResMut, Resource},
|
system::{Commands, Query, Res, ResMut, Resource},
|
||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
};
|
};
|
||||||
use bevy_math::UVec2;
|
use bevy_math::{UVec2, UVec4, Vec4};
|
||||||
use bevy_reflect::{Reflect, TypeUuid};
|
use bevy_reflect::{Reflect, TypeUuid};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::ExtractedCamera,
|
camera::ExtractedCamera,
|
||||||
@ -152,18 +152,27 @@ impl ExtractComponent for BloomSettings {
|
|||||||
return None;
|
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 min_view = size.x.min(size.y) / 2;
|
||||||
let mip_count = calculate_mip_count(min_view);
|
let mip_count = calculate_mip_count(min_view);
|
||||||
let scale = (min_view / 2u32.pow(mip_count)) as f32 / 8.0;
|
let scale = (min_view / 2u32.pow(mip_count)) as f32 / 8.0;
|
||||||
|
|
||||||
BloomUniform {
|
Some(BloomUniform {
|
||||||
threshold: settings.threshold,
|
threshold: settings.threshold,
|
||||||
knee: settings.knee,
|
knee: settings.knee,
|
||||||
scale: settings.scale * scale,
|
scale: settings.scale * scale,
|
||||||
intensity: settings.intensity,
|
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,
|
&bind_groups.prefilter_bind_group,
|
||||||
&[uniform_index.index()],
|
&[uniform_index.index()],
|
||||||
);
|
);
|
||||||
if let Some(viewport) = camera.viewport.as_ref() {
|
|
||||||
prefilter_pass.set_camera_viewport(viewport);
|
|
||||||
}
|
|
||||||
prefilter_pass.draw(0..3, 0..1);
|
prefilter_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,9 +276,6 @@ impl Node for BloomNode {
|
|||||||
&bind_groups.downsampling_bind_groups[mip as usize - 1],
|
&bind_groups.downsampling_bind_groups[mip as usize - 1],
|
||||||
&[uniform_index.index()],
|
&[uniform_index.index()],
|
||||||
);
|
);
|
||||||
if let Some(viewport) = camera.viewport.as_ref() {
|
|
||||||
downsampling_pass.set_camera_viewport(viewport);
|
|
||||||
}
|
|
||||||
downsampling_pass.draw(0..3, 0..1);
|
downsampling_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,9 +297,6 @@ impl Node for BloomNode {
|
|||||||
&bind_groups.upsampling_bind_groups[mip as usize - 1],
|
&bind_groups.upsampling_bind_groups[mip as usize - 1],
|
||||||
&[uniform_index.index()],
|
&[uniform_index.index()],
|
||||||
);
|
);
|
||||||
if let Some(viewport) = camera.viewport.as_ref() {
|
|
||||||
upsampling_pass.set_camera_viewport(viewport);
|
|
||||||
}
|
|
||||||
upsampling_pass.draw(0..3, 0..1);
|
upsampling_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,6 +612,7 @@ pub struct BloomUniform {
|
|||||||
knee: f32,
|
knee: f32,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
intensity: f32,
|
intensity: f32,
|
||||||
|
viewport: Vec4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user