Camera's near plane clips into FogVolume when positioned near its edge
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Bevy version
Bevy v0.15.0-dev 4147422
## What you did
I created a simple scene with a small `FogVolume` and a camera that can move in and out of it.
## What went wrong
When the camera is outside the `FogVolume` and moves towards it, there comes a point when it's positioned near the edge of the AABB that makes up the volume. The camera's near plane clips into the volume and causes it to disappear. After moving further inside, the fog is rendered correctly again.
https://github.com/user-attachments/assets/bde3501b-d9db-49ba-9b30-2b17a49cef64
Minimal reproduction example
use bevy::pbr::{FogVolume, FogVolumeBundle, VolumetricFogSettings, VolumetricLight};
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, move_camera)
.run();
}
fn setup(mut commands: Commands, assets: Res<AssetServer>) {
commands.spawn((
Camera3dBundle {
transform: Transform::from_xyz(1.8, 1.0, 1.0)
.looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
..default()
},
VolumetricFogSettings {
ambient_intensity: 0.0,
..default()
},
));
commands.spawn((
DirectionalLightBundle {
transform: Transform::from_xyz(-6.0, 5.0, -9.0)
.looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
directional_light: DirectionalLight {
illuminance: 32_000.0,
shadows_enabled: true,
..default()
},
..default()
},
VolumetricLight,
));
commands.spawn(FogVolumeBundle {
fog_volume: FogVolume {
density_factor: 1.0,
density_texture: Some(assets.load("volumes/fog_noise.ktx2")),
..default()
},
..default()
});
}
fn move_camera(
keys: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
mut query: Query<&mut Transform, With<Camera>>,
) {
for mut transform in query.iter_mut() {
let mut direction = Vec3::ZERO;
let forward = transform.forward().as_vec3();
let right = transform.right().as_vec3();
let up = transform.up().as_vec3();
for key in keys.get_pressed() {
match key {
KeyCode::KeyW => direction += forward,
KeyCode::KeyS => direction -= forward,
KeyCode::KeyD => direction += right,
KeyCode::KeyA => direction -= right,
KeyCode::KeyE => direction += up,
KeyCode::KeyQ => direction -= up,
_ => (),
}
}
transform.translation += direction.normalize_or_zero() * time.delta_seconds();
}
}
## Additional information
The `FogVolume` implementation from #14099 switches between rendering the volume as a cuboid mesh when the camera is looking at it from the outside and rendering it as a plane scaled to the viewport (effectively making it full-screen) when it's inside. When it's still outside but very close to the volume, the mesh is cut off because of the camera's near plane. Once it moves a little bit further, the fog switches to full-screen rendering and becomes visible again.
Contributor guide
Assessment
This issue has not been assessed yet.