From 910e405ea926e95b0c78dbf80d7f2a30bac64178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Poncabar=C3=A9?= <3194492+terahlunah@users.noreply.github.com> Date: Mon, 24 Feb 2025 22:22:34 +0100 Subject: [PATCH] Allow prepass to run without ATTRIBUTE_NORMAL (#17881) # Objective Allow prepass to run without ATTRIBUTE_NORMAL. This is needed for custom materials with non-standard vertex attributes. For example a voxel material with manually packed vertex data. Fixes #13054. This PR covers the first part of the **stale** PR #13569 to only focus on fixing #13054. ## Solution - Only push normals `vertex_attributes` when the layout contains `Mesh::ATTRIBUTE_NORMAL` ## Testing - Did you test these changes? If so, how? **Tested the fix on my own project with a mesh without normal attribute.** - Are there any parts that need more testing? **I don't think so.** - How can other people (reviewers) test your changes? Is there anything specific they need to know? **Prepass should not be blocked on a mesh without normal attributes (with or without custom material).** - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? **Probably irrelevant, but Windows/Vulkan.** --- crates/bevy_pbr/src/prepass/mod.rs | 9 ++++++++- crates/bevy_pbr/src/prepass/prepass.wgsl | 2 ++ crates/bevy_pbr/src/prepass/prepass_io.wgsl | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 9b3420cbc2..ea60f42667 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -507,8 +507,15 @@ where .mesh_key .intersects(MeshPipelineKey::NORMAL_PREPASS | MeshPipelineKey::DEFERRED_PREPASS) { - vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(3)); shader_defs.push("NORMAL_PREPASS_OR_DEFERRED_PREPASS".into()); + if layout.0.contains(Mesh::ATTRIBUTE_NORMAL) { + shader_defs.push("VERTEX_NORMALS".into()); + vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(3)); + } else if key.mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS) { + warn!( + "The default normal prepass expects the mesh to have vertex normal attributes." + ); + } if layout.0.contains(Mesh::ATTRIBUTE_TANGENT) { shader_defs.push("VERTEX_TANGENTS".into()); vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(4)); diff --git a/crates/bevy_pbr/src/prepass/prepass.wgsl b/crates/bevy_pbr/src/prepass/prepass.wgsl index 26011d609b..52dd9bf201 100644 --- a/crates/bevy_pbr/src/prepass/prepass.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass.wgsl @@ -96,6 +96,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #endif // VERTEX_UVS_B #ifdef NORMAL_PREPASS_OR_DEFERRED_PREPASS +#ifdef VERTEX_NORMALS #ifdef SKINNED out.world_normal = skinning::skin_normals(world_from_local, vertex.normal); #else // SKINNED @@ -106,6 +107,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { vertex_no_morph.instance_index ); #endif // SKINNED +#endif // VERTEX_NORMALS #ifdef VERTEX_TANGENTS out.world_tangent = mesh_functions::mesh_tangent_local_to_world( diff --git a/crates/bevy_pbr/src/prepass/prepass_io.wgsl b/crates/bevy_pbr/src/prepass/prepass_io.wgsl index 5f7d8ec071..c3c0e55549 100644 --- a/crates/bevy_pbr/src/prepass/prepass_io.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass_io.wgsl @@ -15,7 +15,9 @@ struct Vertex { #endif #ifdef NORMAL_PREPASS_OR_DEFERRED_PREPASS +#ifdef VERTEX_NORMALS @location(3) normal: vec3, +#endif #ifdef VERTEX_TANGENTS @location(4) tangent: vec4, #endif