mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
use blendstate blend for alphamode::blend (#7899)
# Objective revert combining pipelines for AlphaMode::Blend and AlphaMode::Premultiplied & Add the recent blend state pr changed `AlphaMode::Blend` to use a blend state of `Blend::PREMULTIPLIED_ALPHA_BLENDING`, and recovered the original behaviour by multiplying colour by alpha in the standard material's fragment shader. this had some advantages (specifically it means more material instances can be batched together in future), but this also means that custom materials that specify `AlphaMode::Blend` now get a premultiplied blend state, so they must also multiply colour by alpha. ## Solution revert that combination to preserve 0.9 behaviour for custom materials with AlphaMode::Blend.
This commit is contained in:
parent
f87de36843
commit
6124b20f4b
5 changed files with 32 additions and 28 deletions
|
@ -445,14 +445,19 @@ pub fn queue_material_meshes<M: Material>(
|
|||
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<M: Material>(
|
|||
|
||||
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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -327,19 +327,7 @@ fn premultiply_alpha(standard_material_flags: u32, color: vec4<f32>) -> vec4<f32
|
|||
//
|
||||
// result = 1 * src_color + (1 - src_alpha) * dst_color
|
||||
let alpha_mode = standard_material_flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS;
|
||||
if alpha_mode == STANDARD_MATERIAL_FLAGS_ALPHA_MODE_BLEND {
|
||||
// Here, we premultiply `src_color` by `src_alpha` (ahead of time, here in the shader)
|
||||
//
|
||||
// src_color *= src_alpha
|
||||
//
|
||||
// We end up with:
|
||||
//
|
||||
// result = 1 * (src_alpha * src_color) + (1 - src_alpha) * dst_color
|
||||
// result = src_alpha * src_color + (1 - src_alpha) * dst_color
|
||||
//
|
||||
// Which is the blend operation for regular alpha blending `BlendState::ALPHA_BLENDING`
|
||||
return vec4<f32>(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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue