Skip to content

Commit 0859f67

Browse files
authored
Use the prepass normal texture in main pass when possible (#8231)
# Objective - We support enabling a normal prepass, but the main pass never actually uses it and recomputes the normals in the main pass. This isn't ideal since it's doing redundant work. ## Solution - Use the normal texture from the prepass in the main pass ## Notes ~~I used `NORMAL_PREPASS_ENABLED` as a shader_def because `NORMAL_PREPASS` is currently used to signify that it is running in the prepass while this shader_def need to indicate the prepass is done and the normal prepass was ran before. I'm not sure if there's a better way to name this.~~
1 parent 21dc3ab commit 0859f67

File tree

3 files changed

+18
-0
lines changed

3 files changed

+18
-0
lines changed

crates/bevy_pbr/src/material.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use bevy_app::{App, Plugin};
77
use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle};
88
use bevy_core_pipeline::{
99
core_3d::{AlphaMask3d, Opaque3d, Transparent3d},
10+
prepass::NormalPrepass,
1011
tonemapping::{DebandDither, Tonemapping},
1112
};
1213
use bevy_derive::{Deref, DerefMut};
@@ -380,6 +381,7 @@ pub fn queue_material_meshes<M: Material>(
380381
Option<&Tonemapping>,
381382
Option<&DebandDither>,
382383
Option<&EnvironmentMapLight>,
384+
Option<&NormalPrepass>,
383385
&mut RenderPhase<Opaque3d>,
384386
&mut RenderPhase<AlphaMask3d>,
385387
&mut RenderPhase<Transparent3d>,
@@ -393,6 +395,7 @@ pub fn queue_material_meshes<M: Material>(
393395
tonemapping,
394396
dither,
395397
environment_map,
398+
normal_prepass,
396399
mut opaque_phase,
397400
mut alpha_mask_phase,
398401
mut transparent_phase,
@@ -405,6 +408,10 @@ pub fn queue_material_meshes<M: Material>(
405408
let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
406409
| MeshPipelineKey::from_hdr(view.hdr);
407410

411+
if normal_prepass.is_some() {
412+
view_key |= MeshPipelineKey::NORMAL_PREPASS;
413+
}
414+
408415
let environment_map_loaded = match environment_map {
409416
Some(environment_map) => environment_map.is_loaded(&images),
410417
None => false,

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,10 @@ impl SpecializedMeshPipeline for MeshPipeline {
665665
let mut shader_defs = Vec::new();
666666
let mut vertex_attributes = Vec::new();
667667

668+
if key.contains(MeshPipelineKey::NORMAL_PREPASS) {
669+
shader_defs.push("LOAD_PREPASS_NORMALS".into());
670+
}
671+
668672
if layout.contains(Mesh::ATTRIBUTE_POSITION) {
669673
shader_defs.push("VERTEX_POSITIONS".into());
670674
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));

crates/bevy_pbr/src/render/pbr.wgsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#import bevy_pbr::fog
1111
#import bevy_pbr::pbr_functions
1212

13+
#import bevy_pbr::prepass_utils
14+
1315
struct FragmentInput {
1416
@builtin(front_facing) is_front: bool,
1517
@builtin(position) frag_coord: vec4<f32>,
@@ -69,11 +71,16 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
6971
#endif
7072
pbr_input.frag_coord = in.frag_coord;
7173
pbr_input.world_position = in.world_position;
74+
75+
#ifdef LOAD_PREPASS_NORMALS
76+
pbr_input.world_normal = prepass_normal(in.frag_coord, 0u);
77+
#else // LOAD_PREPASS_NORMALS
7278
pbr_input.world_normal = prepare_world_normal(
7379
in.world_normal,
7480
(material.flags & STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u,
7581
in.is_front,
7682
);
83+
#endif // LOAD_PREPASS_NORMALS
7784

7885
pbr_input.is_orthographic = view.projection[3].w == 1.0;
7986

0 commit comments

Comments
 (0)