diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 9a2ead7c7232b..cb57e68f4d0dd 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -445,14 +445,19 @@ pub fn queue_material_meshes( let mut mesh_key = MeshPipelineKey::from_primitive_topology(mesh.primitive_topology) | view_key; - let alpha_mode = material.properties.alpha_mode; - if let AlphaMode::Blend | AlphaMode::Premultiplied | AlphaMode::Add = alpha_mode - { - // Blend, Premultiplied and Add all share the same pipeline key - // They're made distinct in the PBR shader, via `premultiply_alpha()` - mesh_key |= MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA; - } else if let AlphaMode::Multiply = alpha_mode { - mesh_key |= MeshPipelineKey::BLEND_MULTIPLY; + match material.properties.alpha_mode { + AlphaMode::Blend => { + mesh_key |= MeshPipelineKey::BLEND_ALPHA; + } + AlphaMode::Premultiplied | AlphaMode::Add => { + // Premultiplied and Add share the same pipeline key + // They're made distinct in the PBR shader, via `premultiply_alpha()` + mesh_key |= MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA; + } + AlphaMode::Multiply => { + mesh_key |= MeshPipelineKey::BLEND_MULTIPLY; + } + _ => (), } let pipeline_id = pipelines.specialize( @@ -474,7 +479,7 @@ pub fn queue_material_meshes( let distance = rangefinder.distance(&mesh_uniform.transform) + material.properties.depth_bias; - match alpha_mode { + match material.properties.alpha_mode { AlphaMode::Opaque => { opaque_phase.add(Opaque3d { entity: *visible_entity, diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 407c357a230e4..855d1e4ae8e33 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -235,6 +235,9 @@ where if blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA { shader_defs.push("BLEND_PREMULTIPLIED_ALPHA".into()); } + if blend_key == MeshPipelineKey::BLEND_ALPHA { + shader_defs.push("BLEND_ALPHA".into()); + } if layout.contains(Mesh::ATTRIBUTE_POSITION) { shader_defs.push("VERTEX_POSITIONS".into()); @@ -285,7 +288,8 @@ where // or the material uses alpha cutoff values and doesn't rely on the standard prepass shader let fragment = if key.mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS) || ((key.mesh_key.contains(MeshPipelineKey::ALPHA_MASK) - || blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA) + || blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA + || blend_key == MeshPipelineKey::BLEND_ALPHA) && self.material_fragment_shader.is_some()) { // Use the fragment shader from the material if present diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 67bb0c7138196..9b1239099bfd8 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -574,6 +574,7 @@ bitflags::bitflags! { const BLEND_OPAQUE = (0 << Self::BLEND_SHIFT_BITS); // ← Values are just sequential within the mask, and can range from 0 to 3 const BLEND_PREMULTIPLIED_ALPHA = (1 << Self::BLEND_SHIFT_BITS); // const BLEND_MULTIPLY = (2 << Self::BLEND_SHIFT_BITS); // ← We still have room for one more value without adding more bits + const BLEND_ALPHA = (3 << Self::BLEND_SHIFT_BITS); const MSAA_RESERVED_BITS = Self::MSAA_MASK_BITS << Self::MSAA_SHIFT_BITS; const PRIMITIVE_TOPOLOGY_RESERVED_BITS = Self::PRIMITIVE_TOPOLOGY_MASK_BITS << Self::PRIMITIVE_TOPOLOGY_SHIFT_BITS; const TONEMAP_METHOD_RESERVED_BITS = Self::TONEMAP_METHOD_MASK_BITS << Self::TONEMAP_METHOD_SHIFT_BITS; @@ -708,7 +709,13 @@ impl SpecializedMeshPipeline for MeshPipeline { let (label, blend, depth_write_enabled); let pass = key.intersection(MeshPipelineKey::BLEND_RESERVED_BITS); - if pass == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA { + if pass == MeshPipelineKey::BLEND_ALPHA { + label = "alpha_blend_mesh_pipeline".into(); + blend = Some(BlendState::ALPHA_BLENDING); + // For the transparent pass, fragments that are closer will be alpha blended + // but their depth is not written to the depth buffer + depth_write_enabled = false; + } else if pass == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA { label = "premultiplied_alpha_mesh_pipeline".into(); blend = Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING); shader_defs.push("PREMULTIPLY_ALPHA".into()); diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index 5cb140b6f412f..45f42268c0e64 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -327,19 +327,7 @@ fn premultiply_alpha(standard_material_flags: u32, color: vec4) -> vec4(color.rgb * color.a, color.a); - } else if alpha_mode == STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ADD { + if alpha_mode == STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ADD { // Here, we premultiply `src_color` by `src_alpha`, and replace `src_alpha` with 0.0: // // src_color *= src_alpha diff --git a/crates/bevy_pbr/src/render/pbr_prepass.wgsl b/crates/bevy_pbr/src/render/pbr_prepass.wgsl index e6efe84c34681..a305e658b9207 100644 --- a/crates/bevy_pbr/src/render/pbr_prepass.wgsl +++ b/crates/bevy_pbr/src/render/pbr_prepass.wgsl @@ -28,9 +28,11 @@ fn prepass_alpha_discard(in: FragmentInput) { // #if defined(ALPHA_MASK) || defined(BLEND_PREMULTIPLIED_ALPHA) #ifndef ALPHA_MASK #ifndef BLEND_PREMULTIPLIED_ALPHA +#ifndef BLEND_ALPHA #define EMPTY_PREPASS_ALPHA_DISCARD +#endif // BLEND_ALPHA #endif // BLEND_PREMULTIPLIED_ALPHA not defined #endif // ALPHA_MASK not defined @@ -47,9 +49,7 @@ fn prepass_alpha_discard(in: FragmentInput) { if ((material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK) != 0u) && output_color.a < material.alpha_cutoff { discard; } -#endif // ALPHA_MASK - -#ifdef BLEND_PREMULTIPLIED_ALPHA +#else // BLEND_PREMULTIPLIED_ALPHA || BLEND_ALPHA let alpha_mode = material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS; if (alpha_mode == STANDARD_MATERIAL_FLAGS_ALPHA_MODE_BLEND || alpha_mode == STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ADD) && output_color.a < PREMULTIPLIED_ALPHA_CUTOFF { @@ -58,7 +58,7 @@ fn prepass_alpha_discard(in: FragmentInput) { && all(output_color < vec4(PREMULTIPLIED_ALPHA_CUTOFF)) { discard; } -#endif // BLEND_PREMULTIPLIED_ALPHA +#endif // !ALPHA_MASK #endif // EMPTY_PREPASS_ALPHA_DISCARD not defined }