From c2ab3a0402449322e5bbef48a854a7ac01a029bc Mon Sep 17 00:00:00 2001 From: Marco Buono Date: Mon, 1 Jan 2024 14:04:20 -0300 Subject: [PATCH] Do not load prepass normals for transmissive materials (#11140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out whenever a normal prepass was active (which includes whenever you use SSAO) we were attempting to read the normals from the prepass for the specular transmissive material. Since transmissive materials don't participate in the prepass (unlike opaque materials) we were reading the normals from “behind” the mesh, producing really weird visual results. # Objective - Fixes #11112. ## Solution - We introduce a new `READS_VIEW_TRANSMISSION_TEXTURE` mesh pipeline key; - We set it whenever the material properties has the `reads_view_transmission_texture` flag set; (i.e. the material is transmissive) - If this key is set we prevent the reading of normals from the prepass, by not setting the `LOAD_PREPASS_NORMALS` shader def. --- ## Changelog ### Fixed - Specular transmissive materials no longer attempt to erroneously load prepass normals, and now work correctly even with the normal prepass active (e.g. when using SSAO) --- crates/bevy_pbr/src/material.rs | 5 +++++ crates/bevy_pbr/src/render/mesh.rs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index f729b5b3e2..356c489627 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -606,6 +606,11 @@ pub fn queue_material_meshes( if mesh.morph_targets.is_some() { mesh_key |= MeshPipelineKey::MORPH_TARGETS; } + + if material.properties.reads_view_transmission_texture { + mesh_key |= MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE; + } + mesh_key |= alpha_mode_pipeline_key(material.properties.alpha_mode); let pipeline_id = pipelines.specialize( diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 867f37680f..cb1579b376 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -491,6 +491,7 @@ bitflags::bitflags! { const DEPTH_CLAMP_ORTHO = 1 << 10; const TEMPORAL_JITTER = 1 << 11; const MORPH_TARGETS = 1 << 12; + const READS_VIEW_TRANSMISSION_TEXTURE = 1 << 13; const BLEND_RESERVED_BITS = Self::BLEND_MASK_BITS << Self::BLEND_SHIFT_BITS; // ← Bitmask reserving bits for the blend state 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; // @@ -737,7 +738,7 @@ impl SpecializedMeshPipeline for MeshPipeline { // the current fragment value in the output and the depth is written to the // depth buffer depth_write_enabled = true; - is_opaque = true; + is_opaque = !key.contains(MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE); } if key.contains(MeshPipelineKey::NORMAL_PREPASS) {