Bevy version and features
- v0.19.0 (default features, Linux x86_64, Vulkan)
What you did
Tried to brighten a world-scale fog bank (tens of units deep) with the camera's VolumetricFog::ambient_intensity, the parameter the docs designate for ambient/skylight in-scatter:
// Camera with ambient fog in-scatter.
commands.spawn((
Camera3d::default(),
Hdr,
VolumetricFog {
ambient_intensity: 8.0, // <- has no visible effect on the fog bank
step_count: 64,
jitter: 0.0,
..default()
},
Transform::from_xyz(0.0, 4.0, 16.0).looking_at(Vec3::new(0.0, 3.0, 0.0), Vec3::Y),
));
// A world-scale fog bank: rays toward the sky cross ~60 units of fog.
commands.spawn((
FogVolume {
density_factor: 0.15,
scattering: 0.6,
absorption: 0.05,
..default()
},
Transform::from_xyz(0.0, 5.0, -22.0).with_scale(Vec3::new(100.0, 20.0, 60.0)),
));
// ...swap the scale for Vec3::splat(4.0) and the parameter works as expected.
// VolumetricLight is required for the pass to run at all; with shadow maps
// disabled the directional light contributes zero in-scatter, so the ambient
// term is the only possible fog illumination in this scene.
commands.spawn((
DirectionalLight {
illuminance: 12000.0,
shadow_maps_enabled: false,
..default()
},
VolumetricLight,
Transform::from_rotation(Quat::from_euler(EulerRot::XYZ, -1.0, 0.4, 0.0)),
));
Full runnable reproduction:
https://github.com/blaind/bevy-volumetric-ambient-repro (VOLUME=large|small AMBIENT=0|8)
What went wrong
- Expected: raising
ambient_intensity brightens the fog, most visibly where the fog is thickest.
- Actually: the parameter is numerically dead where it matters. Measured max per-pixel delta between ambient 0 and ambient 8 in the upper half of the frame (fog against the sky, ~60 units of fog along the ray): 10/255, mean 0.13. Only short rays to nearby geometry respond (max 122/255 in the foreground), so fog brightness decreases with thickness, which is physically inverted. Shrinking the same volume to 4x4x4 (the regime of the shipped examples) makes the parameter work fine (max 138/255), which is presumably why this went unnoticed.
Cause, the closed-form ambient term in crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl:
// Use Beer's law again to accumulate the ambient light all along the path.
var accumulated_color = exp(-ray_length_view * (absorption + scattering)) * ambient_color *
ambient_intensity;
It applies extinction over the entire in-fog ray length at implicit density 1.0 (density_factor and the density texture are never consulted for ambient), so for a 60-unit path with absorption + scattering = 0.65 the factor is exp(-39), i.e. zero for any ambient_intensity. The comment says "accumulate the ambient light all along the path", but the code models only light entering at the far end of the ray.
Additional information
- Suggested code for investigating fix (degrades performance - should not be merged as is) included in the repro as
fix-volumetric-ambient-in-scatter.patch: initialize the accumulator to zero and integrate ambient per step, mirroring the existing per-light march. Verified: bit-exact no-op at intensity 0, monotonic response, identical with shadows on/off.
100x20x60 volume, ambient 0, baseline (extinction only):

100x20x60 volume, ambient 8, the bug: fog against the sky stays black, only the short-path foreground responds, brightness falls with fog thickness:
4x4x4 volume, ambient 8, control: at example scale the parameter works:

100x20x60 volume, ambient 8, with the fix: brightness now increases with fog thickness (8 is deliberately extreme; calibrated values sit around 1-2):

Bevy version and features
What you did
Tried to brighten a world-scale fog bank (tens of units deep) with the camera's
VolumetricFog::ambient_intensity, the parameter the docs designate for ambient/skylight in-scatter:Full runnable reproduction:
https://github.com/blaind/bevy-volumetric-ambient-repro (
VOLUME=large|small AMBIENT=0|8)What went wrong
ambient_intensitybrightens the fog, most visibly where the fog is thickest.Cause, the closed-form ambient term in
crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl:It applies extinction over the entire in-fog ray length at implicit density 1.0 (
density_factorand the density texture are never consulted for ambient), so for a 60-unit path withabsorption + scattering = 0.65the factor isexp(-39), i.e. zero for anyambient_intensity. The comment says "accumulate the ambient light all along the path", but the code models only light entering at the far end of the ray.Additional information
fix-volumetric-ambient-in-scatter.patch: initialize the accumulator to zero and integrate ambient per step, mirroring the existing per-light march. Verified: bit-exact no-op at intensity 0, monotonic response, identical with shadows on/off.100x20x60 volume, ambient 0, baseline (extinction only):

100x20x60 volume, ambient 8, the bug: fog against the sky stays black, only the short-path foreground responds, brightness falls with fog thickness:
4x4x4 volume, ambient 8, control: at example scale the parameter works:

100x20x60 volume, ambient 8, with the fix: brightness now increases with fog thickness (8 is deliberately extreme; calibrated values sit around 1-2):