AlphaMode::Blend produces non-opague shape when defined as opague when used with fog
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## Bevy version and features
0.19.0
0.19.1
and main
## What you did
I have a scene with a cuboid with an opague blend material and I noticed something is wrong with the depth when the cuboid is between my fog god ray and the camera causing it to render transparent.
## What went wrong
Its suppose to be opague its rendering transparent
## Additional information
minimized repro
```rs
use bevy::{
asset::RenderAssetUsages,
camera::Exposure,
camera_controller::free_camera::{FreeCamera, FreeCameraPlugin},
core_pipeline::{prepass::DepthPrepass, tonemapping::Tonemapping},
light::{FogVolume, VolumetricFog, VolumetricLight},
post_process::bloom::Bloom,
prelude::*,
render::render_resource::{Extent3d, TextureDimension, TextureFormat},
};
const SURFACE_Y: f32 = 0.0;
const BOTTOM_Y: f32 = SURFACE_Y - 45.0;
const GOD_RAY_LIGHT_HEIGHT: f32 = 20.0;
const GOD_RAY_RANGE: f32 = 200.0;
const COLLAR_INNER_RADIUS: f32 = 2.5;
const COLLAR_HEIGHT: f32 = 0.8;
const GOD_RAY_FOG_WIDTH: f32 = 12.0;
const GOD_RAY_BRIGHTNESS: f32 = 3_000_000.0;
const PLAYER_CUBOID_SIZE: Vec3 = Vec3::new(0.5, 1.5, 0.5);
const PLAYER_POSITION: Vec3 = Vec3::new(6.5, -5.0, 0.0);
const EXPOSURE_EV100: f32 = 5.5;
fn main() {
App::new()
.add_plugins((DefaultPlugins, FreeCameraPlugin))
.insert_resource(ClearColor(Color::BLACK))
.add_systems(Startup, (setup_camera, setup_god_ray, setup_player))
.run();
}
fn setup_camera(mut commands: Commands) {
commands.spawn((
Camera3d::default(),
Transform::from_xyz(11.5, -4.6, 0.0).looking_at(Vec3::new(0.0, -6.0, 0.0), Vec3::Y),
FreeCamera::default(),
DepthPrepass,
Msaa::Off,
Exposure {
ev100: EXPOSURE_EV100,
},
Tonemapping::AcesFitted,
Bloom::NATURAL,
AmbientLight {
brightness: 0.0,
..default()
},
VolumetricFog {
ambient_intensity: 0.0,
..default()
},
));
}
fn setup_god_ray(mut commands: Commands, mut images: ResMut>) {
let outer_angle = (COLLAR_INNER_RADIUS / GOD_RAY_LIGHT_HEIGHT).atan();
commands.spawn((
SpotLight {
color: Color::WHITE,
intensity: GOD_RAY_BRIGHTNESS,
range: GOD_RAY_RANGE,
shadow_maps_enabled: true,
inner_angle: outer_angle * 0.7,
outer_angle,
..default()
},
VolumetricLight,
Transform::from_xyz(0.0, SURFACE_Y + GOD_RAY_LIGHT_HEIGHT, 0.0)
.looking_at(Vec3::new(0.0, BOTTOM_Y, 0.0), Vec3::Z),
));
let fog_top = SURFACE_Y + COLLAR_HEIGHT;
commands.spawn((
FogVolume {
density_factor: 0.04,
absorption: 0.05,
scattering: 0.5,
light_intensity: 8.0,
density_texture: Some(images.add(god_ray_density_image())),
..default()
},
Transform::from_xyz(0.0, (BOTTOM_Y + fog_top) / 2.0, 0.0).with_scale(Vec3::new(
GOD_RAY_FOG_WIDTH,
fog_top - BOTTOM_Y,
GOD_RAY_FOG_WIDTH,
)),
));
}
fn setup_player(
mut commands: Commands,
mut meshes: ResMut>,
mut materials: ResMut>,
) {
let mesh = meshes.add(Cuboid::from_size(PLAYER_CUBOID_SIZE));
commands.spawn((
Mesh3d(mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.8, 0.3, 0.3),
..default()
})),
Transform::from_translation(PLAYER_POSITION + Vec3::new(0.0, 0.0, -0.6)),
));
commands.spawn((
Mesh3d(mesh),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgba(0.8, 0.3, 0.3, 1.0),
alpha_mode: AlphaMode::Blend,
..default()
})),
Transform::from_translation(PLAYER_POSITION + Vec3::new(0.0, 0.0, 0.6)),
));
commands.spawn((
PointLight {
color: Color::srgb(1.0, 0.85, 0.6),
intensity: 300_000.0,
range: 40.0,
shadow_maps_enabled: false,
..default()
},
Transform::from_translation(PLAYER_POSITION + Vec3::new(4.0, 2.0, 2.5)),
));
}
fn god_ray_density_image() -> Image {
const N: usize = 32;
let mut data = vec![0u8; N * N * N];
for z in 0..N {
for y in 0..N {
for x in 0..N {
let dx = x as f32 / (N - 1) as f32 * 2.0 - 1.0;
let dz = z as f32 / (N - 1) as f32 * 2.0 - 1.0;
let r = (dx * dx + dz * dz).sqrt();
let t = ((1.0 - r) / 0.3).clamp(0.0, 1.0);
let d = t * t * (3.0 - 2.0 * t);
data[(z * N + y) * N + x] = (d * 255.0) as u8;
}
}
}
Image::new(
Extent3d {
width: N as u32,
height: N as u32,
depth_or_array_layers: N as u32,
},
TextureDimension::D3,
data,
TextureFormat::R8Unorm,
RenderAssetUsages::RENDER_WORLD,
)
}
```
Contributor guide
Research direction
Run the minimized Rust reproduction and compare the two cuboids created in setup_player while tracing the camera and volumetric fog configured in setup_camera and setup_god_ray. Identify why the AlphaMode::Blend cuboid becomes transparent through fog, and consider the issue done when it remains opaque as expected in the reported setup.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics, game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100