Open SludgePhD opened 1 year ago
Upon further investigation it looks like this is just a consequence of render-to-texture performing proper alpha blending on the texture, while the direct rendering ignores the alpha channel (or rather, the OS compositor ignores it). The alpha value for all pixels outside of geometry stays 0, even if the bloom effects the pixel.
It seems like this would be fixed if the bloom shader computed proper alpha values (and blended those to the target frame buffer) instead of using the blend constant like it does now, which is the same issue as pointed out by this comment:
Bevy version
Reproduces on 0.10.0 and current master (d193d7f53734ca3d35e55e1d7fc0d4fd20cb97d6)
[Optional] Relevant system information
Tested on Arch Linux and this adapter:
What you did
I modified the
bloom_3d.rs
example to this:Code
```rust //! Illustrates bloom post-processing using HDR and emissive materials. use bevy::{ core_pipeline::{ bloom::{BloomCompositeMode, BloomSettings}, clear_color::ClearColorConfig, tonemapping::Tonemapping, }, prelude::*, render::{ camera::RenderTarget, render_resource::{ Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, }, view::RenderLayers, }, }; use std::{ collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, }; fn main() { App::new() .insert_resource(ClearColor(Color::DARK_GRAY)) .add_plugins(DefaultPlugins) .add_systems(Startup, setup_scene) .add_systems(Update, (update_bloom_settings, bounce_spheres)) .run(); } fn setup_scene( mut commands: Commands, mut meshes: ResMut>,
mut materials: ResMut>,
mut images: ResMut>,
asset_server: Res,
) {
let size = Extent3d {
width: 1280,
height: 720,
..Default::default()
};
let mut image = Image {
texture_descriptor: TextureDescriptor {
label: None,
size,
dimension: TextureDimension::D2,
format: TextureFormat::Bgra8UnormSrgb,
mip_level_count: 1,
sample_count: 1,
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
},
..default()
};
image.resize(size);
let target = images.add(image);
commands.spawn((
Camera3dBundle {
camera: Camera {
hdr: true, // 1. HDR is required for bloom
target: RenderTarget::Image(target.clone()),
..default()
},
camera_3d: Camera3d {
clear_color: ClearColorConfig::Custom(Color::NONE),
..Default::default()
},
tonemapping: Tonemapping::TonyMcMapface, // 2. Using a tonemapper that desaturates to white is recommended
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
BloomSettings::default(), // 3. Enable bloom for the camera
));
let compose_layer = RenderLayers::layer(1);
commands.spawn((
Camera2dBundle {
camera: Camera {
order: 1, // should be rendered last
..default()
},
camera_2d: Camera2d {
clear_color: ClearColorConfig::Custom(Color::NONE),
..Default::default()
},
..Default::default()
},
compose_layer,
));
commands.spawn((
SpriteBundle {
texture: target,
..default()
},
compose_layer,
));
let material_emissive1 = materials.add(StandardMaterial {
emissive: Color::rgb_linear(13.99, 5.32, 2.0), // 4. Put something bright in a dark environment to see the effect
..default()
});
let material_emissive2 = materials.add(StandardMaterial {
emissive: Color::rgb_linear(2.0, 13.99, 5.32),
..default()
});
let material_emissive3 = materials.add(StandardMaterial {
emissive: Color::rgb_linear(5.32, 2.0, 13.99),
..default()
});
let material_non_emissive = materials.add(StandardMaterial {
base_color: Color::GRAY,
..default()
});
let mesh = meshes.add(
shape::Icosphere {
radius: 0.5,
subdivisions: 5,
}
.try_into()
.unwrap(),
);
for x in -10..10 {
for z in -10..10 {
let mut hasher = DefaultHasher::new();
(x, z).hash(&mut hasher);
let rand = (hasher.finish() - 2) % 6;
let material = match rand {
0 => material_emissive1.clone(),
1 => material_emissive2.clone(),
2 => material_emissive3.clone(),
3 | 4 | 5 => material_non_emissive.clone(),
_ => unreachable!(),
};
commands.spawn((
PbrBundle {
mesh: mesh.clone(),
material,
transform: Transform::from_xyz(x as f32 * 2.0, 0.0, z as f32 * 2.0),
..default()
},
Bouncing,
));
}
}
commands.spawn(
TextBundle::from_section(
"",
TextStyle {
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
font_size: 18.0,
color: Color::BLACK,
},
)
.with_style(Style {
position_type: PositionType::Absolute,
bottom: Val::Px(10.0),
left: Val::Px(10.0),
..default()
}),
);
}
// ------------------------------------------------------------------------------------------------
fn update_bloom_settings(
mut camera: Query<(Entity, Option<&mut BloomSettings>), With>,
mut text: Query<&mut Text>,
mut commands: Commands,
keycode: Res>,
time: Res
What went wrong
I expected this to result in basically the same result you get when rendering to the window directly (with the clear color set to
Color::NONE
). Instead, the bloom effect only appears on the example geometry, not on the non-covered parts of the backing texture.Additional information
Here's a screenshot of the original
bloom_3d.rs
example, modified to use aColor::NONE
clear color:Here's one from the modified example code provided above: