Skip to content

Commit

Permalink
Do not load prepass normals for transmissive materials (#11140)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
coreh authored Jan 1, 2024
1 parent 17ef731 commit c2ab3a0
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 1 deletion.
5 changes: 5 additions & 0 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,11 @@ pub fn queue_material_meshes<M: Material>(
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(
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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; //
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit c2ab3a0

Please sign in to comment.