From 56838c13a8fbb3df211aa254fc16c687736a8196 Mon Sep 17 00:00:00 2001 From: Jeroen H <10060956+JeroenHoogers@users.noreply.github.com> Date: Sun, 10 May 2026 23:27:29 +0200 Subject: [PATCH 1/2] fixed spotlight shadow issue due to incorrect matrix reconstruction --- crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl b/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl index 04e40eeabe73b..84a10a20323fb 100644 --- a/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl +++ b/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl @@ -479,15 +479,16 @@ fn fetch_spot_shadow_without_normal(light_id: u32, frag_position: vec4, fra + ((*light).shadow_depth_bias * normalize(surface_to_light)); // the construction of the up and right vectors needs to precisely mirror the code - // in render/light.rs:spot_light_view_matrix + // in light/spot_light.rs:orthonormalize var sign = -1.0; if (fwd.z >= 0.0) { sign = 1.0; } let a = -1.0 / (fwd.z + sign); let b = fwd.x * fwd.y * a; - let up_dir = vec3(1.0 + sign * fwd.x * fwd.x * a, sign * b, -sign * fwd.x); - let right_dir = vec3(-b, -sign - fwd.y * fwd.y * a, fwd.y); + let right_dir = vec3(1.0 + sign * fwd.x * fwd.x * a, sign * b, -sign * fwd.x); + let up_dir = vec3(b, sign + fwd.y * fwd.y * a, -fwd.y); + let light_inv_rot = mat3x3(right_dir, up_dir, fwd); // because the matrix is a pure rotation matrix, the inverse is just the transpose, and to calculate From 10a0cbe52fcddc6121693c84a9cfc23032b8fa2e Mon Sep 17 00:00:00 2001 From: Jeroen H <10060956+JeroenHoogers@users.noreply.github.com> Date: Mon, 11 May 2026 19:11:24 +0200 Subject: [PATCH 2/2] replaced basis calculation in volumetric fog code with a call to maths::orthonormalize() --- .../src/volumetric_fog/volumetric_fog.wgsl | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl b/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl index 84a10a20323fb..a5ca6b74fa27f 100644 --- a/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl +++ b/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl @@ -44,6 +44,7 @@ position_ndc_to_world, position_view_to_world } +#import bevy_render::maths::orthonormalize #import bevy_pbr::clustered_forward as clustering #import bevy_pbr::lighting::getDistanceAttenuation; @@ -478,18 +479,7 @@ fn fetch_spot_shadow_without_normal(light_id: u32, frag_position: vec4, fra -surface_to_light + ((*light).shadow_depth_bias * normalize(surface_to_light)); - // the construction of the up and right vectors needs to precisely mirror the code - // in light/spot_light.rs:orthonormalize - var sign = -1.0; - if (fwd.z >= 0.0) { - sign = 1.0; - } - let a = -1.0 / (fwd.z + sign); - let b = fwd.x * fwd.y * a; - let right_dir = vec3(1.0 + sign * fwd.x * fwd.x * a, sign * b, -sign * fwd.x); - let up_dir = vec3(b, sign + fwd.y * fwd.y * a, -fwd.y); - - let light_inv_rot = mat3x3(right_dir, up_dir, fwd); + let light_inv_rot = orthonormalize(fwd); // because the matrix is a pure rotation matrix, the inverse is just the transpose, and to calculate // the product of the transpose with a vector we can just post-multiply instead of pre-multiplying.