diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index be28f2e13a5e9..a0fa33252be79 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -7,6 +7,7 @@ use bevy_app::{App, Plugin}; use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle}; use bevy_core_pipeline::{ core_3d::{AlphaMask3d, Opaque3d, Transparent3d}, + prepass::NormalPrepass, tonemapping::{DebandDither, Tonemapping}, }; use bevy_derive::{Deref, DerefMut}; @@ -380,6 +381,7 @@ pub fn queue_material_meshes( Option<&Tonemapping>, Option<&DebandDither>, Option<&EnvironmentMapLight>, + Option<&NormalPrepass>, &mut RenderPhase, &mut RenderPhase, &mut RenderPhase, @@ -393,6 +395,7 @@ pub fn queue_material_meshes( tonemapping, dither, environment_map, + normal_prepass, mut opaque_phase, mut alpha_mask_phase, mut transparent_phase, @@ -405,6 +408,10 @@ pub fn queue_material_meshes( let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) | MeshPipelineKey::from_hdr(view.hdr); + if normal_prepass.is_some() { + view_key |= MeshPipelineKey::NORMAL_PREPASS; + } + let environment_map_loaded = match environment_map { Some(environment_map) => environment_map.is_loaded(&images), None => false, diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index a76ff0f470712..6a2ce1c6f9021 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -657,6 +657,10 @@ impl SpecializedMeshPipeline for MeshPipeline { let mut shader_defs = Vec::new(); let mut vertex_attributes = Vec::new(); + if key.contains(MeshPipelineKey::NORMAL_PREPASS) { + shader_defs.push("LOAD_PREPASS_NORMALS".into()); + } + if layout.contains(Mesh::ATTRIBUTE_POSITION) { shader_defs.push("VERTEX_POSITIONS".into()); vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0)); diff --git a/crates/bevy_pbr/src/render/pbr.wgsl b/crates/bevy_pbr/src/render/pbr.wgsl index b87208edca6b3..f97c2c23ed67c 100644 --- a/crates/bevy_pbr/src/render/pbr.wgsl +++ b/crates/bevy_pbr/src/render/pbr.wgsl @@ -10,6 +10,8 @@ #import bevy_pbr::fog #import bevy_pbr::pbr_functions +#import bevy_pbr::prepass_utils + struct FragmentInput { @builtin(front_facing) is_front: bool, @builtin(position) frag_coord: vec4, @@ -69,11 +71,16 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { #endif pbr_input.frag_coord = in.frag_coord; pbr_input.world_position = in.world_position; + +#ifdef LOAD_PREPASS_NORMALS + pbr_input.world_normal = prepass_normal(in.frag_coord, 0u); +#else // LOAD_PREPASS_NORMALS pbr_input.world_normal = prepare_world_normal( in.world_normal, (material.flags & STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u, in.is_front, ); +#endif // LOAD_PREPASS_NORMALS pbr_input.is_orthographic = view.projection[3].w == 1.0;