mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Expose max_mip_dimension and uv_offset in BloomSettings. (#14512)
# Objective By default, Bevy's bloom effect shows square artifacts on small bright particles due to a low max mip resolution. This PR makes this configurable via BloomSettings so users can customize these parameters instead of having them in private module constants. ## Solution Expose max_mip_dimension and uv_offset in BloomSettings. ## Testing I tested these changes by running the Bloom 2D / 3D examples. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
6183b56b5d
commit
882973a528
4 changed files with 27 additions and 11 deletions
|
@ -10,6 +10,7 @@ struct BloomUniforms {
|
||||||
threshold_precomputations: vec4<f32>,
|
threshold_precomputations: vec4<f32>,
|
||||||
viewport: vec4<f32>,
|
viewport: vec4<f32>,
|
||||||
aspect: f32,
|
aspect: f32,
|
||||||
|
uv_offset: f32
|
||||||
};
|
};
|
||||||
|
|
||||||
@group(0) @binding(0) var input_texture: texture_2d<f32>;
|
@group(0) @binding(0) var input_texture: texture_2d<f32>;
|
||||||
|
@ -94,9 +95,9 @@ fn sample_input_13_tap(uv: vec2<f32>) -> vec3<f32> {
|
||||||
|
|
||||||
// [COD] slide 162
|
// [COD] slide 162
|
||||||
fn sample_input_3x3_tent(uv: vec2<f32>) -> vec3<f32> {
|
fn sample_input_3x3_tent(uv: vec2<f32>) -> vec3<f32> {
|
||||||
// Radius. Empirically chosen by and tweaked from the LearnOpenGL article.
|
// UV offsets configured from uniforms.
|
||||||
let x = 0.004 / uniforms.aspect;
|
let x = uniforms.uv_offset / uniforms.aspect;
|
||||||
let y = 0.004;
|
let y = uniforms.uv_offset;
|
||||||
|
|
||||||
let a = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y + y)).rgb;
|
let a = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y + y)).rgb;
|
||||||
let b = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y + y)).rgb;
|
let b = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y + y)).rgb;
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub struct BloomUniforms {
|
||||||
pub threshold_precomputations: Vec4,
|
pub threshold_precomputations: Vec4,
|
||||||
pub viewport: Vec4,
|
pub viewport: Vec4,
|
||||||
pub aspect: f32,
|
pub aspect: f32,
|
||||||
|
pub uv_offset: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for BloomDownsamplingPipeline {
|
impl FromWorld for BloomDownsamplingPipeline {
|
||||||
|
|
|
@ -38,10 +38,6 @@ const BLOOM_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(9295994769239
|
||||||
|
|
||||||
const BLOOM_TEXTURE_FORMAT: TextureFormat = TextureFormat::Rg11b10Float;
|
const BLOOM_TEXTURE_FORMAT: TextureFormat = TextureFormat::Rg11b10Float;
|
||||||
|
|
||||||
// Maximum size of each dimension for the largest mipchain texture used in downscaling/upscaling.
|
|
||||||
// 512 behaves well with the UV offset of 0.004 used in bloom.wgsl
|
|
||||||
const MAX_MIP_DIMENSION: u32 = 512;
|
|
||||||
|
|
||||||
pub struct BloomPlugin;
|
pub struct BloomPlugin;
|
||||||
|
|
||||||
impl Plugin for BloomPlugin {
|
impl Plugin for BloomPlugin {
|
||||||
|
@ -328,18 +324,18 @@ fn prepare_bloom_textures(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut texture_cache: ResMut<TextureCache>,
|
mut texture_cache: ResMut<TextureCache>,
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
views: Query<(Entity, &ExtractedCamera), With<BloomSettings>>,
|
views: Query<(Entity, &ExtractedCamera, &BloomSettings)>,
|
||||||
) {
|
) {
|
||||||
for (entity, camera) in &views {
|
for (entity, camera, settings) in &views {
|
||||||
if let Some(UVec2 {
|
if let Some(UVec2 {
|
||||||
x: width,
|
x: width,
|
||||||
y: height,
|
y: height,
|
||||||
}) = camera.physical_viewport_size
|
}) = camera.physical_viewport_size
|
||||||
{
|
{
|
||||||
// How many times we can halve the resolution minus one so we don't go unnecessarily low
|
// How many times we can halve the resolution minus one so we don't go unnecessarily low
|
||||||
let mip_count = MAX_MIP_DIMENSION.ilog2().max(2) - 1;
|
let mip_count = settings.max_mip_dimension.ilog2().max(2) - 1;
|
||||||
let mip_height_ratio = if height != 0 {
|
let mip_height_ratio = if height != 0 {
|
||||||
MAX_MIP_DIMENSION as f32 / height as f32
|
settings.max_mip_dimension as f32 / height as f32
|
||||||
} else {
|
} else {
|
||||||
0.
|
0.
|
||||||
};
|
};
|
||||||
|
|
|
@ -102,9 +102,20 @@ pub struct BloomSettings {
|
||||||
/// configured in a non-energy-conserving way,
|
/// configured in a non-energy-conserving way,
|
||||||
/// otherwise set to [`BloomCompositeMode::EnergyConserving`].
|
/// otherwise set to [`BloomCompositeMode::EnergyConserving`].
|
||||||
pub composite_mode: BloomCompositeMode,
|
pub composite_mode: BloomCompositeMode,
|
||||||
|
|
||||||
|
/// Maximum size of each dimension for the largest mipchain texture used in downscaling/upscaling.
|
||||||
|
/// Only tweak if you are seeing visual artifacts.
|
||||||
|
pub max_mip_dimension: u32,
|
||||||
|
|
||||||
|
/// UV offset for bloom shader. Ideally close to 2.0 / `max_mip_dimension`.
|
||||||
|
/// Only tweak if you are seeing visual artifacts.
|
||||||
|
pub uv_offset: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BloomSettings {
|
impl BloomSettings {
|
||||||
|
const DEFAULT_MAX_MIP_DIMENSION: u32 = 512;
|
||||||
|
const DEFAULT_UV_OFFSET: f32 = 0.004;
|
||||||
|
|
||||||
/// The default bloom preset.
|
/// The default bloom preset.
|
||||||
///
|
///
|
||||||
/// This uses the [`EnergyConserving`](BloomCompositeMode::EnergyConserving) composite mode.
|
/// This uses the [`EnergyConserving`](BloomCompositeMode::EnergyConserving) composite mode.
|
||||||
|
@ -118,6 +129,8 @@ impl BloomSettings {
|
||||||
threshold_softness: 0.0,
|
threshold_softness: 0.0,
|
||||||
},
|
},
|
||||||
composite_mode: BloomCompositeMode::EnergyConserving,
|
composite_mode: BloomCompositeMode::EnergyConserving,
|
||||||
|
max_mip_dimension: Self::DEFAULT_MAX_MIP_DIMENSION,
|
||||||
|
uv_offset: Self::DEFAULT_UV_OFFSET,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A preset that's similar to how older games did bloom.
|
/// A preset that's similar to how older games did bloom.
|
||||||
|
@ -131,6 +144,8 @@ impl BloomSettings {
|
||||||
threshold_softness: 0.2,
|
threshold_softness: 0.2,
|
||||||
},
|
},
|
||||||
composite_mode: BloomCompositeMode::Additive,
|
composite_mode: BloomCompositeMode::Additive,
|
||||||
|
max_mip_dimension: Self::DEFAULT_MAX_MIP_DIMENSION,
|
||||||
|
uv_offset: Self::DEFAULT_UV_OFFSET,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A preset that applies a very strong bloom, and blurs the whole screen.
|
/// A preset that applies a very strong bloom, and blurs the whole screen.
|
||||||
|
@ -144,6 +159,8 @@ impl BloomSettings {
|
||||||
threshold_softness: 0.0,
|
threshold_softness: 0.0,
|
||||||
},
|
},
|
||||||
composite_mode: BloomCompositeMode::EnergyConserving,
|
composite_mode: BloomCompositeMode::EnergyConserving,
|
||||||
|
max_mip_dimension: Self::DEFAULT_MAX_MIP_DIMENSION,
|
||||||
|
uv_offset: Self::DEFAULT_UV_OFFSET,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +230,7 @@ impl ExtractComponent for BloomSettings {
|
||||||
/ UVec4::new(target_size.x, target_size.y, target_size.x, target_size.y)
|
/ UVec4::new(target_size.x, target_size.y, target_size.x, target_size.y)
|
||||||
.as_vec4(),
|
.as_vec4(),
|
||||||
aspect: AspectRatio::from_pixels(size.x, size.y).into(),
|
aspect: AspectRatio::from_pixels(size.x, size.y).into(),
|
||||||
|
uv_offset: settings.uv_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((settings.clone(), uniform))
|
Some((settings.clone(), uniform))
|
||||||
|
|
Loading…
Reference in a new issue