bevyengine / bevyengine/bevy

Camera's near plane clips into FogVolume when positioned near its edge

Open
#15,008 1 comment 1 reaction 0 assignees View on GitHub
A-Rendering C-Bug D-Straightforward
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.