diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index 2c862958dd223..33e550c01c768 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -12,6 +12,7 @@ shadows, ambient, irradiance_volume, + view_transformations, mesh_types::{MESH_FLAGS_SHADOW_RECEIVER_BIT, MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT}, } #import bevy_render::maths::{E, powsafe} @@ -767,19 +768,34 @@ fn apply_fog(fog_params: mesh_view_types::Fog, input_color: vec4, fragment_ // fog shape that looks a bit fake let distance = length(view_to_world); + // Calculate view_z for shadow cascade selection + let view_pos = view_transformations::position_world_to_view(fragment_world_position); + let view_z = view_pos.z; + + // Approximate surface normal using view direction for shadow sampling + let view_direction_normal = normalize(-view_to_world); + let fragment_world_position_vec4 = vec4(fragment_world_position, 1.0); + var scattering = vec3(0.0); if fog_params.directional_light_color.a > 0.0 { let view_to_world_normalized = view_to_world / distance; let n_directional_lights = view_bindings::lights.n_directional_lights; for (var i: u32 = 0u; i < n_directional_lights; i = i + 1u) { - let light = view_bindings::lights.directional_lights[i]; - scattering += pow( + let light = view_bindings::lights.directional_lights[i]; + let scattering_contribution = pow( max( dot(view_to_world_normalized, light.direction_to_light), 0.0 ), fog_params.directional_light_exponent ) * light.color.rgb * view_bindings::view.exposure; + + // Sample shadow map to attenuate inscattering in shadowed areas + var shadow: f32 = 1.0; + if ((light.flags & mesh_view_types::DIRECTIONAL_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) { + shadow = shadows::fetch_directional_shadow(i, fragment_world_position_vec4, view_direction_normal, view_z); + } + scattering += scattering_contribution * shadow; } }