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

[Merged by Bors] - bevy_pbr: Support flipping tangent space normal map y for DirectX normal maps #4433

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 8 additions & 0 deletions crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ pub struct StandardMaterial {
/// defaults to 0.5 which is mapped to 4% reflectance in the shader
pub reflectance: f32,
pub normal_map_texture: Option<Handle<Image>>,
/// Normal map textures authored for DirectX have their y-component flipped. Set this to flip
/// it to right-handed conventions.
pub flip_normal_map_y: bool,
pub occlusion_texture: Option<Handle<Image>>,
/// Support two-sided lighting by automatically flipping the normals for "back" faces
/// within the PBR lighting shader.
Expand Down Expand Up @@ -84,6 +87,7 @@ impl Default for StandardMaterial {
reflectance: 0.5,
occlusion_texture: None,
normal_map_texture: None,
flip_normal_map_y: false,
double_sided: false,
cull_mode: Some(Face::Back),
unlit: false,
Expand Down Expand Up @@ -124,6 +128,7 @@ bitflags::bitflags! {
const ALPHA_MODE_MASK = (1 << 7);
const ALPHA_MODE_BLEND = (1 << 8);
const TWO_COMPONENT_NORMAL_MAP = (1 << 9);
const FLIP_NORMAL_MAP_Y = (1 << 10);
const NONE = 0;
const UNINITIALIZED = 0xFFFF;
}
Expand Down Expand Up @@ -262,6 +267,9 @@ impl RenderAsset for StandardMaterial {
}
_ => {}
}
if material.flip_normal_map_y {
flags |= StandardMaterialFlags::FLIP_NORMAL_MAP_Y;
}
}
// NOTE: 0.5 is from the glTF default - do we want this?
let mut alpha_cutoff = 0.5;
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_pbr/src/render/pbr.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE: u32 = 64u;
let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK: u32 = 128u;
let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_BLEND: u32 = 256u;
let STANDARD_MATERIAL_FLAGS_TWO_COMPONENT_NORMAL_MAP: u32 = 512u;
let STANDARD_MATERIAL_FLAGS_FLIP_NORMAL_MAP_Y: u32 = 1024u;

[[group(1), binding(0)]]
var<uniform> material: StandardMaterial;
Expand Down Expand Up @@ -525,6 +526,10 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
} else {
Nt = textureSample(normal_map_texture, normal_map_sampler, in.uv).rgb * 2.0 - 1.0;
}
// Normal maps authored for DirectX require flipping the y component
if ((material.flags & STANDARD_MATERIAL_FLAGS_FLIP_NORMAL_MAP_Y) != 0u) {
Nt.y = -Nt.y;
}
N = normalize(TBN * Nt);
#endif
#endif
Expand Down