Skip to content

Commit 882973a

Browse files
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 <[email protected]>
1 parent 6183b56 commit 882973a

File tree

4 files changed

+27
-11
lines changed

4 files changed

+27
-11
lines changed

crates/bevy_core_pipeline/src/bloom/bloom.wgsl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct BloomUniforms {
1010
threshold_precomputations: vec4<f32>,
1111
viewport: vec4<f32>,
1212
aspect: f32,
13+
uv_offset: f32
1314
};
1415

1516
@group(0) @binding(0) var input_texture: texture_2d<f32>;
@@ -94,9 +95,9 @@ fn sample_input_13_tap(uv: vec2<f32>) -> vec3<f32> {
9495

9596
// [COD] slide 162
9697
fn sample_input_3x3_tent(uv: vec2<f32>) -> vec3<f32> {
97-
// Radius. Empirically chosen by and tweaked from the LearnOpenGL article.
98-
let x = 0.004 / uniforms.aspect;
99-
let y = 0.004;
98+
// UV offsets configured from uniforms.
99+
let x = uniforms.uv_offset / uniforms.aspect;
100+
let y = uniforms.uv_offset;
100101

101102
let a = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y + y)).rgb;
102103
let b = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y + y)).rgb;

crates/bevy_core_pipeline/src/bloom/downsampling_pipeline.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub struct BloomUniforms {
4141
pub threshold_precomputations: Vec4,
4242
pub viewport: Vec4,
4343
pub aspect: f32,
44+
pub uv_offset: f32,
4445
}
4546

4647
impl FromWorld for BloomDownsamplingPipeline {

crates/bevy_core_pipeline/src/bloom/mod.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ const BLOOM_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(9295994769239
3838

3939
const BLOOM_TEXTURE_FORMAT: TextureFormat = TextureFormat::Rg11b10Float;
4040

41-
// Maximum size of each dimension for the largest mipchain texture used in downscaling/upscaling.
42-
// 512 behaves well with the UV offset of 0.004 used in bloom.wgsl
43-
const MAX_MIP_DIMENSION: u32 = 512;
44-
4541
pub struct BloomPlugin;
4642

4743
impl Plugin for BloomPlugin {
@@ -328,18 +324,18 @@ fn prepare_bloom_textures(
328324
mut commands: Commands,
329325
mut texture_cache: ResMut<TextureCache>,
330326
render_device: Res<RenderDevice>,
331-
views: Query<(Entity, &ExtractedCamera), With<BloomSettings>>,
327+
views: Query<(Entity, &ExtractedCamera, &BloomSettings)>,
332328
) {
333-
for (entity, camera) in &views {
329+
for (entity, camera, settings) in &views {
334330
if let Some(UVec2 {
335331
x: width,
336332
y: height,
337333
}) = camera.physical_viewport_size
338334
{
339335
// How many times we can halve the resolution minus one so we don't go unnecessarily low
340-
let mip_count = MAX_MIP_DIMENSION.ilog2().max(2) - 1;
336+
let mip_count = settings.max_mip_dimension.ilog2().max(2) - 1;
341337
let mip_height_ratio = if height != 0 {
342-
MAX_MIP_DIMENSION as f32 / height as f32
338+
settings.max_mip_dimension as f32 / height as f32
343339
} else {
344340
0.
345341
};

crates/bevy_core_pipeline/src/bloom/settings.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,20 @@ pub struct BloomSettings {
102102
/// configured in a non-energy-conserving way,
103103
/// otherwise set to [`BloomCompositeMode::EnergyConserving`].
104104
pub composite_mode: BloomCompositeMode,
105+
106+
/// Maximum size of each dimension for the largest mipchain texture used in downscaling/upscaling.
107+
/// Only tweak if you are seeing visual artifacts.
108+
pub max_mip_dimension: u32,
109+
110+
/// UV offset for bloom shader. Ideally close to 2.0 / `max_mip_dimension`.
111+
/// Only tweak if you are seeing visual artifacts.
112+
pub uv_offset: f32,
105113
}
106114

107115
impl BloomSettings {
116+
const DEFAULT_MAX_MIP_DIMENSION: u32 = 512;
117+
const DEFAULT_UV_OFFSET: f32 = 0.004;
118+
108119
/// The default bloom preset.
109120
///
110121
/// This uses the [`EnergyConserving`](BloomCompositeMode::EnergyConserving) composite mode.
@@ -118,6 +129,8 @@ impl BloomSettings {
118129
threshold_softness: 0.0,
119130
},
120131
composite_mode: BloomCompositeMode::EnergyConserving,
132+
max_mip_dimension: Self::DEFAULT_MAX_MIP_DIMENSION,
133+
uv_offset: Self::DEFAULT_UV_OFFSET,
121134
};
122135

123136
/// A preset that's similar to how older games did bloom.
@@ -131,6 +144,8 @@ impl BloomSettings {
131144
threshold_softness: 0.2,
132145
},
133146
composite_mode: BloomCompositeMode::Additive,
147+
max_mip_dimension: Self::DEFAULT_MAX_MIP_DIMENSION,
148+
uv_offset: Self::DEFAULT_UV_OFFSET,
134149
};
135150

136151
/// A preset that applies a very strong bloom, and blurs the whole screen.
@@ -144,6 +159,8 @@ impl BloomSettings {
144159
threshold_softness: 0.0,
145160
},
146161
composite_mode: BloomCompositeMode::EnergyConserving,
162+
max_mip_dimension: Self::DEFAULT_MAX_MIP_DIMENSION,
163+
uv_offset: Self::DEFAULT_UV_OFFSET,
147164
};
148165
}
149166

@@ -213,6 +230,7 @@ impl ExtractComponent for BloomSettings {
213230
/ UVec4::new(target_size.x, target_size.y, target_size.x, target_size.y)
214231
.as_vec4(),
215232
aspect: AspectRatio::from_pixels(size.x, size.y).into(),
233+
uv_offset: settings.uv_offset,
216234
};
217235

218236
Some((settings.clone(), uniform))

0 commit comments

Comments
 (0)