Skip to content

Commit

Permalink
bevy_pbr: Fix negation of normal for back-side when no normal map
Browse files Browse the repository at this point in the history
  • Loading branch information
superdump committed Aug 22, 2022
1 parent 8025c0f commit dbf9097
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 10 deletions.
13 changes: 9 additions & 4 deletions assets/shaders/array_texture.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var my_array_texture: texture_2d_array<f32>;
var my_array_texture_sampler: sampler;

struct FragmentInput {
@builtin(front_facing) is_front: bool,
@builtin(position) frag_coord: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
};
Expand All @@ -33,13 +34,17 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {

pbr_input.frag_coord = in.frag_coord;
pbr_input.world_position = in.world_position;
pbr_input.world_normal = in.world_normal;
pbr_input.world_normal = prepare_world_normal(
in.world_normal,
(material.flags & STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u,
in.is_front,
);

pbr_input.is_orthographic = view.projection[3].w == 1.0;

pbr_input.N = prepare_normal(
pbr_input.material.flags,
in.world_normal,
pbr_input.N = apply_normal_mapping(
material.flags,
pbr_input.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
in.world_tangent,
Expand Down
11 changes: 8 additions & 3 deletions crates/bevy_pbr/src/render/pbr.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import bevy_pbr::pbr_functions

struct FragmentInput {
@builtin(front_facing) is_front: bool,
@builtin(position) frag_coord: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
};
Expand Down Expand Up @@ -68,13 +69,17 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {

pbr_input.frag_coord = in.frag_coord;
pbr_input.world_position = in.world_position;
pbr_input.world_normal = in.world_normal;
pbr_input.world_normal = prepare_world_normal(
in.world_normal,
(material.flags & STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u,
in.is_front,
);

pbr_input.is_orthographic = view.projection[3].w == 1.0;

pbr_input.N = prepare_normal(
pbr_input.N = apply_normal_mapping(
material.flags,
in.world_normal,
pbr_input.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
in.world_tangent,
Expand Down
20 changes: 17 additions & 3 deletions crates/bevy_pbr/src/render/pbr_functions.wgsl
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
#define_import_path bevy_pbr::pbr_functions

// NOTE: This ensures that the world_normal is normalized and if
// vertex tangents and normal maps then normal mapping may be applied.
fn prepare_normal(
fn prepare_world_normal(
world_normal: vec3<f32>,
double_sided: bool,
is_front: bool,
) -> vec3<f32> {
var output: vec3<f32> = world_normal;
#ifndef VERTEX_TANGENTS
#ifndef STANDARDMATERIAL_NORMAL_MAP
// NOTE: When NOT using normal-mapping, if looking at the back face of a double-sided
// material, the normal needs to be inverted. This is a branchless version of that.
output = (f32(!double_sided || is_front) * 2.0 - 1.0) * output;
#endif
#endif
return output;
}

fn apply_normal_mapping(
standard_material_flags: u32,
world_normal: vec3<f32>,
#ifdef VERTEX_TANGENTS
Expand Down

0 comments on commit dbf9097

Please sign in to comment.