diff --git a/crates/bevy_pbr/src/render/shadow_sampling.wgsl b/crates/bevy_pbr/src/render/shadow_sampling.wgsl index c7f7253a63..2b35e57037 100644 --- a/crates/bevy_pbr/src/render/shadow_sampling.wgsl +++ b/crates/bevy_pbr/src/render/shadow_sampling.wgsl @@ -422,11 +422,7 @@ fn sample_shadow_cubemap_gaussian( ) -> f32 { // Create an orthonormal basis so we can apply a 2D sampling pattern to a // cubemap. - var up = vec3(0.0, 1.0, 0.0); - if (dot(up, normalize(light_local)) > 0.99) { - up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis. - } - let basis = orthonormalize(light_local, up) * scale * distance_to_light; + let basis = orthonormalize(normalize(light_local)) * scale * distance_to_light; var sum: f32 = 0.0; sum += sample_shadow_cubemap_at_offset( @@ -469,11 +465,7 @@ fn sample_shadow_cubemap_jittered( ) -> f32 { // Create an orthonormal basis so we can apply a 2D sampling pattern to a // cubemap. - var up = vec3(0.0, 1.0, 0.0); - if (dot(up, normalize(light_local)) > 0.99) { - up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis. - } - let basis = orthonormalize(light_local, up) * scale * distance_to_light; + let basis = orthonormalize(normalize(light_local)) * scale * distance_to_light; let rotation_matrix = random_rotation_matrix(vec2(1.0), temporal); @@ -553,11 +545,7 @@ fn search_for_blockers_in_shadow_cubemap( ) -> f32 { // Create an orthonormal basis so we can apply a 2D sampling pattern to a // cubemap. - var up = vec3(0.0, 1.0, 0.0); - if (dot(up, normalize(light_local)) > 0.99) { - up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis. - } - let basis = orthonormalize(light_local, up) * scale * distance_to_light; + let basis = orthonormalize(normalize(light_local)) * scale * distance_to_light; var sum: vec2 = vec2(0.0); sum += search_for_blockers_in_shadow_cubemap_at_offset( diff --git a/crates/bevy_render/src/maths.wgsl b/crates/bevy_render/src/maths.wgsl index d1e35523dc..0f9a11076f 100644 --- a/crates/bevy_render/src/maths.wgsl +++ b/crates/bevy_render/src/maths.wgsl @@ -63,17 +63,19 @@ fn mat4x4_to_mat3x3(m: mat4x4) -> mat3x3 { return mat3x3(m[0].xyz, m[1].xyz, m[2].xyz); } -// Creates an orthonormal basis given a Z vector and an up vector (which becomes -// Y after orthonormalization). +// Creates an orthonormal basis given a normalized Z vector. // // The results are equivalent to the Gram-Schmidt process [1]. // // [1]: https://math.stackexchange.com/a/1849294 -fn orthonormalize(z_unnormalized: vec3, up: vec3) -> mat3x3 { - let z_basis = normalize(z_unnormalized); - let x_basis = normalize(cross(z_basis, up)); - let y_basis = cross(z_basis, x_basis); - return mat3x3(x_basis, y_basis, z_basis); +fn orthonormalize(z_normalized: vec3) -> mat3x3 { + var up = vec3(0.0, 1.0, 0.0); + if (abs(dot(up, z_normalized)) > 0.99) { + up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis. + } + let x_basis = normalize(cross(z_normalized, up)); + let y_basis = cross(z_normalized, x_basis); + return mat3x3(x_basis, y_basis, z_normalized); } // Returns true if any part of a sphere is on the positive side of a plane.