From f42ecc44f8656f1ad62ff55c9f4dea91db67b0b1 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Mon, 3 Mar 2025 06:22:36 +0000 Subject: [PATCH] Fix panic with multiple fog volumes (#18119) # Objective Fixes https://github.com/bevyengine/bevy/issues/17590. ## Solution `prepare_volumetric_fog_uniforms` adds a uniform for each combination of fog volume and view. But it only allocated enough uniforms for one fog volume per view. ## Testing Ran the `volumetric_fog` example with 1/2/3/4 fog volumes. Also checked the `fog_volumes` and `scrolling_fog` examples (without multiple volumes). Win10/Vulkan/Nvidia. To test multiple views I tried adding fog volumes to the `split_screen` example. This doesn't quite work - the fog should be centred on the fox, but instead it's centred on the window. Same result with and without the PR, so I'm assuming it's a separate bug. ![image](https://github.com/user-attachments/assets/4a74d6d7-8a73-4322-9dc6-c5ddd054ece2) --- crates/bevy_pbr/src/volumetric_fog/render.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/bevy_pbr/src/volumetric_fog/render.rs b/crates/bevy_pbr/src/volumetric_fog/render.rs index 292ad1c86ae1a..632a6f2c30a72 100644 --- a/crates/bevy_pbr/src/volumetric_fog/render.rs +++ b/crates/bevy_pbr/src/volumetric_fog/render.rs @@ -694,20 +694,20 @@ pub fn prepare_volumetric_fog_uniforms( render_queue: Res, mut local_from_world_matrices: Local>, ) { - let Some(mut writer) = volumetric_lighting_uniform_buffer.get_writer( - view_targets.iter().len(), - &render_device, - &render_queue, - ) else { - return; - }; - // Do this up front to avoid O(n^2) matrix inversion. local_from_world_matrices.clear(); for (_, _, fog_transform) in fog_volumes.iter() { local_from_world_matrices.push(fog_transform.compute_matrix().inverse()); } + let uniform_count = view_targets.iter().len() * local_from_world_matrices.len(); + + let Some(mut writer) = + volumetric_lighting_uniform_buffer.get_writer(uniform_count, &render_device, &render_queue) + else { + return; + }; + for (view_entity, extracted_view, volumetric_fog) in view_targets.iter() { let world_from_view = extracted_view.world_from_view.compute_matrix();