Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,37 +472,43 @@ pub(crate) struct CubeMapFace {
pub(crate) up: Vec3,
}

// see https://www.khronos.org/opengl/wiki/Cubemap_Texture
// Cubemap faces are [+X, -X, +Y, -Y, +Z, -Z], per https://www.w3.org/TR/webgpu/#texture-view-creation
// Note: Cubemap coordinates are left-handed y-up, unlike the rest of Bevy.
// See https://registry.khronos.org/vulkan/specs/1.2/html/chap16.html#_cube_map_face_selection
//
// For each cubemap face, we take care to specify the appropriate target/up axis such that the rendered
// texture using Bevy's right-handed y-up coordinate space matches the expected cubemap face in
// left-handed y-up cubemap coordinates.
pub(crate) const CUBE_MAP_FACES: [CubeMapFace; 6] = [
// 0 GL_TEXTURE_CUBE_MAP_POSITIVE_X
// +X
CubeMapFace {
target: Vec3::NEG_X,
up: Vec3::NEG_Y,
target: Vec3::X,
up: Vec3::Y,
},
// 1 GL_TEXTURE_CUBE_MAP_NEGATIVE_X
// -X
CubeMapFace {
target: Vec3::X,
up: Vec3::NEG_Y,
target: Vec3::NEG_X,
up: Vec3::Y,
},
// 2 GL_TEXTURE_CUBE_MAP_POSITIVE_Y
// +Y
CubeMapFace {
target: Vec3::NEG_Y,
target: Vec3::Y,
up: Vec3::Z,
},
// 3 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
// -Y
CubeMapFace {
target: Vec3::Y,
target: Vec3::NEG_Y,
up: Vec3::NEG_Z,
},
// 4 GL_TEXTURE_CUBE_MAP_POSITIVE_Z
// +Z (with left-handed conventions, pointing forwards)
CubeMapFace {
target: Vec3::NEG_Z,
up: Vec3::NEG_Y,
up: Vec3::Y,
},
// 5 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
// -Z (with left-handed conventions, pointing backwards)
CubeMapFace {
target: Vec3::Z,
up: Vec3::NEG_Y,
up: Vec3::Y,
},
];

Expand Down
11 changes: 7 additions & 4 deletions crates/bevy_pbr/src/render/shadows.wgsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#define_import_path bevy_pbr::shadows

const flip_z: vec3<f32> = vec3<f32>(1.0, 1.0, -1.0);

fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: vec3<f32>) -> f32 {
let light = &point_lights.data[light_id];

Expand All @@ -17,7 +19,7 @@ fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: v
let offset_position = frag_position.xyz + normal_offset + depth_offset;

// similar largest-absolute-axis trick as above, but now with the offset fragment position
let frag_ls = (*light).position_radius.xyz - offset_position.xyz;
let frag_ls = offset_position.xyz - (*light).position_radius.xyz ;
let abs_position_ls = abs(frag_ls);
let major_axis_magnitude = max(abs_position_ls.x, max(abs_position_ls.y, abs_position_ls.z));

Expand All @@ -28,16 +30,17 @@ fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: v
let zw = -major_axis_magnitude * (*light).light_custom_data.xy + (*light).light_custom_data.zw;
let depth = zw.x / zw.y;

// do the lookup, using HW PCF and comparison
// Do the lookup, using HW PCF and comparison. Cubemaps assume a left-handed coordinate space,
// so we have to flip the z-axis when sampling.
// NOTE: Due to the non-uniform control flow above, we must use the Level variant of
// textureSampleCompare to avoid undefined behaviour due to some of the fragments in
// a quad (2x2 fragments) being processed not being sampled, and this messing with
// mip-mapping functionality. The shadow maps have no mipmaps so Level just samples
// from LOD 0.
#ifdef NO_ARRAY_TEXTURES_SUPPORT
return textureSampleCompare(point_shadow_textures, point_shadow_textures_sampler, frag_ls, depth);
return textureSampleCompare(point_shadow_textures, point_shadow_textures_sampler, frag_ls * flip_z, depth);
#else
return textureSampleCompareLevel(point_shadow_textures, point_shadow_textures_sampler, frag_ls, i32(light_id), depth);
return textureSampleCompareLevel(point_shadow_textures, point_shadow_textures_sampler, frag_ls * flip_z, i32(light_id), depth);
#endif
}

Expand Down