diff --git a/crates/bevy_light/src/spot_light.rs b/crates/bevy_light/src/spot_light.rs index 0df3c8995515f..5e18d0899a136 100644 --- a/crates/bevy_light/src/spot_light.rs +++ b/crates/bevy_light/src/spot_light.rs @@ -171,19 +171,15 @@ pub fn orthonormalize(z_basis: Dir3) -> Mat3 { let y_basis = Vec3::new(b, sign + z_basis.y * z_basis.y * a, -z_basis.y); Mat3::from_cols(x_basis, y_basis, z_basis.into()) } -/// Constructs a left-handed orthonormal basis with translation, using only the forward direction and translation of a given [`GlobalTransform`]. +/// Constructs a right-handed orthonormal basis with translation, using only the forward direction and translation of a given [`GlobalTransform`]. /// -/// This is a handedness-inverted version of [`orthonormalize`] which also includes translation. -/// we mirror this construction in the fragment shader and need our implementations to match exactly. -// See bevy_pbr/shadows.wgsl:spot_light_world_from_view +/// This is a version of [`orthonormalize`] which also includes translation. pub fn spot_light_world_from_view(transform: &GlobalTransform) -> Mat4 { // the matrix z_local (opposite of transform.forward()) let fwd_dir = transform.back(); let basis = orthonormalize(fwd_dir); let mut mat = Mat4::from_mat3(basis); - // handedness flip - mat.x_axis = -mat.x_axis; mat.w_axis = transform.translation().extend(1.0); mat } diff --git a/crates/bevy_pbr/src/render/shadows.wgsl b/crates/bevy_pbr/src/render/shadows.wgsl index 0672cf79ad61f..a3727b45af526 100644 --- a/crates/bevy_pbr/src/render/shadows.wgsl +++ b/crates/bevy_pbr/src/render/shadows.wgsl @@ -62,21 +62,6 @@ fn fetch_point_shadow(light_id: u32, frag_position: vec4, surface_normal: v return sample_shadow_cubemap(frag_ls * flip_z, distance_to_light, depth, light_id); } -// Constructs a left-handed orthonormal basis from a given unit Z vector. -// -// NOTE: requires unit-length (normalized) input to function properly. -// -// this method of constructing a basis from a vec3 is used by glam::Vec3::any_orthonormal_pair -// the construction of the orthonormal basis up and right vectors here needs to precisely mirror the code -// in bevy_light/spot_light.rs:spot_light_world_from_view -// so we use `bevy_math::orthonormalize` which matches the rust impl, but we also invert the handedness -fn spot_light_world_from_view(z_basis: vec3) -> mat3x3 { - var basis = orthonormalize(z_basis); - // handedness flip - basis[0] = -basis[0]; - return basis; -} - fn fetch_spot_shadow( light_id: u32, frag_position: vec4, @@ -103,7 +88,7 @@ fn fetch_spot_shadow( + ((*light).shadow_depth_bias * normalize(surface_to_light)) + (surface_normal.xyz * (*light).shadow_normal_bias) * distance_to_light; - let light_inv_rot = spot_light_world_from_view(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. diff --git a/crates/bevy_render/src/maths.wgsl b/crates/bevy_render/src/maths.wgsl index 31311a69a78a9..a5c556f9f1104 100644 --- a/crates/bevy_render/src/maths.wgsl +++ b/crates/bevy_render/src/maths.wgsl @@ -75,6 +75,8 @@ fn copysign(a: f32, b: f32) -> f32 { // // https://jcgt.org/published/0006/01/01/paper.pdf // this method of constructing a basis from a vec3 is also used by `glam::Vec3::any_orthonormal_pair` +// the construction of the orthonormal basis up and right vectors here needs to precisely match the rust +// implementation in bevy_light/spot_light.rs:spot_light_world_from_view fn orthonormalize(z_basis: vec3) -> mat3x3 { let sign = copysign(1.0, z_basis.z); let a = -1.0 / (sign + z_basis.z);