Skip to content

Commit dc1f76d

Browse files
authored
Fix handling of double_sided for normal maps (#10326)
# Objective Right now, we flip the `world_normal` in response to `double_sided && !is_front`, however when calculating `N` from tangents and the normal map, we don't flip the normal read from the normal map, which produces extremely weird results. ## Solution - Pass `double_sided` and `is_front` flags to the `apply_normal_mapping()` function and use them to conditionally flip `Nt` ## Comparison Note: These are from a custom scene running with the `transmission` branch, (#8015) I noticed lighting got pretty weird for the back side of translucent `double_sided` materials whenever I added a normal map. ### Before <img width="1392" alt="Screenshot 2023-10-31 at 01 26 06" src="https://github.com/bevyengine/bevy/assets/418473/d5f8c9c3-aca1-4c2f-854d-f0d0fd2fb19a"> ### After <img width="1392" alt="Screenshot 2023-10-31 at 01 25 42" src="https://github.com/bevyengine/bevy/assets/418473/fa0e1aa2-19ad-4c27-bb08-37299d97971c"> --- ## Changelog - Fixed a bug where `StandardMaterial::double_sided` would interact incorrectly with normal maps, producing broken results.
1 parent 3628e09 commit dc1f76d

File tree

2 files changed

+9
-0
lines changed

2 files changed

+9
-0
lines changed

crates/bevy_pbr/src/render/pbr_fragment.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ fn pbr_input_from_standard_material(
148148
pbr_input.N = pbr_functions::apply_normal_mapping(
149149
pbr_bindings::material.flags,
150150
pbr_input.world_normal,
151+
double_sided,
152+
is_front,
151153
#ifdef VERTEX_TANGENTS
152154
#ifdef STANDARDMATERIAL_NORMAL_MAP
153155
in.world_tangent,

crates/bevy_pbr/src/render/pbr_functions.wgsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ fn prepare_world_normal(
6161
fn apply_normal_mapping(
6262
standard_material_flags: u32,
6363
world_normal: vec3<f32>,
64+
double_sided: bool,
65+
is_front: bool,
6466
#ifdef VERTEX_TANGENTS
6567
#ifdef STANDARDMATERIAL_NORMAL_MAP
6668
world_tangent: vec4<f32>,
@@ -106,6 +108,11 @@ fn apply_normal_mapping(
106108
if (standard_material_flags & pbr_types::STANDARD_MATERIAL_FLAGS_FLIP_NORMAL_MAP_Y) != 0u {
107109
Nt.y = -Nt.y;
108110
}
111+
112+
if double_sided && !is_front {
113+
Nt = -Nt;
114+
}
115+
109116
// NOTE: The mikktspace method of normal mapping applies maps the tangent-space normal from
110117
// the normal map texture in this way to be an EXACT inverse of how the normal map baker
111118
// calculates the normal maps so there is no error introduced. Do not change this code

0 commit comments

Comments
 (0)