Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Left-handed y-up cubemap coordinates #8122

Merged
merged 3 commits into from
Mar 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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

var<private> flip_z: vec3<f32> = vec3<f32>(1.0, 1.0, -1.0);
danchia marked this conversation as resolved.
Show resolved Hide resolved

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