Skip to content

Commit

Permalink
use alpha mask even when unlit (#6047)
Browse files Browse the repository at this point in the history
# Objective

- Alpha mask was previously ignored when using an unlit material. 
- Fixes #4479

## Solution

- Extract the alpha discard to a separate function and use it when unlit is true

## Notes
I tried calling `alpha_discard()` before the `if` in pbr.wgsl, but I had errors related to having a `discard` at the beginning before doing the texture sampling. I'm not sure if there's a way to fix that instead of having the function being called in 2 places.
  • Loading branch information
IceSentry committed Sep 28, 2022
1 parent 8073362 commit 197392a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 13 deletions.
2 changes: 2 additions & 0 deletions crates/bevy_pbr/src/render/pbr.wgsl
Expand Up @@ -89,6 +89,8 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
pbr_input.V = calculate_view(in.world_position, pbr_input.is_orthographic);

output_color = tone_mapping(pbr(pbr_input));
} else {
output_color = alpha_discard(material, output_color);
}

return output_color;
Expand Down
33 changes: 20 additions & 13 deletions crates/bevy_pbr/src/render/pbr_functions.wgsl
@@ -1,5 +1,23 @@
#define_import_path bevy_pbr::pbr_functions

fn alpha_discard(material: StandardMaterial, output_color: vec4<f32>) -> vec4<f32>{
var color = output_color;
if ((material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE) != 0u) {
// NOTE: If rendering as opaque, alpha should be ignored so set to 1.0
color.a = 1.0;
} else if ((material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK) != 0u) {
if (color.a >= material.alpha_cutoff) {
// NOTE: If rendering as masked alpha and >= the cutoff, render as fully opaque
color.a = 1.0;
} else {
// NOTE: output_color.a < in.material.alpha_cutoff should not is not rendered
// NOTE: This and any other discards mean that early-z testing cannot be done!
discard;
}
}
return color;
}

// 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(
Expand Down Expand Up @@ -142,19 +160,7 @@ fn pbr(

let occlusion = in.occlusion;

if ((in.material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE) != 0u) {
// NOTE: If rendering as opaque, alpha should be ignored so set to 1.0
output_color.a = 1.0;
} else if ((in.material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK) != 0u) {
if (output_color.a >= in.material.alpha_cutoff) {
// NOTE: If rendering as masked alpha and >= the cutoff, render as fully opaque
output_color.a = 1.0;
} else {
// NOTE: output_color.a < in.material.alpha_cutoff should not is not rendered
// NOTE: This and any other discards mean that early-z testing cannot be done!
discard;
}
}
output_color = alpha_discard(in.material, output_color);

// Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
let NdotV = max(dot(in.N, in.V), 0.0001);
Expand Down Expand Up @@ -247,3 +253,4 @@ fn tone_mapping(in: vec4<f32>) -> vec4<f32> {
// Not needed with sRGB buffer
// output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2));
}

15 changes: 15 additions & 0 deletions examples/3d/transparency_3d.rs
Expand Up @@ -44,6 +44,21 @@ fn setup(
transform: Transform::from_xyz(1.0, 0.5, -1.5),
..default()
});
// transparent unlit sphere, uses `alpha_mode: Mask(f32)`
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere {
radius: 0.5,
subdivisions: 3,
})),
material: materials.add(StandardMaterial {
base_color: Color::rgba(0.2, 0.7, 0.1, 0.0),
alpha_mode: AlphaMode::Mask(0.5),
unlit: true,
..default()
}),
transform: Transform::from_xyz(-1.0, 0.5, -1.5),
..default()
});
// transparent cube, uses `alpha_mode: Blend`
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
Expand Down

0 comments on commit 197392a

Please sign in to comment.