Factor out up-choice in shadow cubemap sampling orthonormalize (#20052)

# Objective

- Another step towards unifying our orthonormal basis construction
#20050
- Preserve behavior but fix a bug. Unification will be a followup after
these two PRs and will need more thorough testing.

## Solution

- Make shadow cubemap sampling orthonormalize have the same function
signature as the other orthonormal basis functions in bevy

## Testing

- 3d_scene + lighting examples
This commit is contained in:
atlv 2025-07-11 08:19:02 -04:00 committed by GitHub
parent b3032e06bd
commit 20dfae9a2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 12 additions and 22 deletions

View File

@ -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<f32> = vec2(0.0);
sum += search_for_blockers_in_shadow_cubemap_at_offset(

View File

@ -63,17 +63,19 @@ fn mat4x4_to_mat3x3(m: mat4x4<f32>) -> mat3x3<f32> {
return mat3x3<f32>(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<f32>, up: vec3<f32>) -> mat3x3<f32> {
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<f32>) -> mat3x3<f32> {
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.