From 740ae9a37f3a5d4d8f019021760f805d55d98a01 Mon Sep 17 00:00:00 2001 From: Charles Date: Mon, 10 Oct 2022 17:58:15 +0000 Subject: [PATCH] remove mandatory mesh attributes (#6127) # Objective - It's possible to create a mesh without positions or normals, but currently bevy forces these attributes to be present on any mesh. ## Solution - Don't assume these attributes are present and add a shader defs for each attributes - I updated 2d and 3d meshes to use the same logic. --- ## Changelog - Meshes don't require any attributes # Notes I didn't update the pbr.wgsl shader because I'm not sure how to handle it. It doesn't really make sense to use it without positions or normals. --- crates/bevy_pbr/src/render/mesh.rs | 17 ++++++++++++----- crates/bevy_pbr/src/render/mesh.wgsl | 15 ++++++++++++++- crates/bevy_sprite/src/mesh2d/mesh.rs | 23 +++++++++++++++++------ crates/bevy_sprite/src/mesh2d/mesh2d.wgsl | 21 +++++++++++++++++++++ 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 34b43a6ed1fa3..698d34b384d6f 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -566,12 +566,19 @@ impl SpecializedMeshPipeline for MeshPipeline { key: Self::Key, layout: &MeshVertexBufferLayout, ) -> Result { - let mut vertex_attributes = vec![ - Mesh::ATTRIBUTE_POSITION.at_shader_location(0), - Mesh::ATTRIBUTE_NORMAL.at_shader_location(1), - ]; - let mut shader_defs = Vec::new(); + let mut vertex_attributes = Vec::new(); + + if layout.contains(Mesh::ATTRIBUTE_POSITION) { + shader_defs.push(String::from("VERTEX_POSITIONS")); + vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0)); + } + + if layout.contains(Mesh::ATTRIBUTE_NORMAL) { + shader_defs.push(String::from("VERTEX_NORMALS")); + vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(1)); + } + if layout.contains(Mesh::ATTRIBUTE_UV_0) { shader_defs.push(String::from("VERTEX_UVS")); vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(2)); diff --git a/crates/bevy_pbr/src/render/mesh.wgsl b/crates/bevy_pbr/src/render/mesh.wgsl index 32cbe31c8d161..266ff804b51b3 100644 --- a/crates/bevy_pbr/src/render/mesh.wgsl +++ b/crates/bevy_pbr/src/render/mesh.wgsl @@ -5,8 +5,12 @@ #import bevy_pbr::mesh_functions struct Vertex { +#ifdef VERTEX_POSITIONS @location(0) position: vec3, +#endif +#ifdef VERTEX_NORMALS @location(1) normal: vec3, +#endif #ifdef VERTEX_UVS @location(2) uv: vec2, #endif @@ -30,6 +34,8 @@ struct VertexOutput { @vertex fn vertex(vertex: Vertex) -> VertexOutput { var out: VertexOutput; + +#ifdef VERTEX_NORMALS #ifdef SKINNED var model = skin_model(vertex.joint_indices, vertex.joint_weights); out.world_normal = skin_normals(model, vertex.normal); @@ -37,18 +43,25 @@ fn vertex(vertex: Vertex) -> VertexOutput { var model = mesh.model; out.world_normal = mesh_normal_local_to_world(vertex.normal); #endif +#endif + +#ifdef VERTEX_POSITIONS out.world_position = mesh_position_local_to_world(model, vec4(vertex.position, 1.0)); + out.clip_position = mesh_position_world_to_clip(out.world_position); +#endif + #ifdef VERTEX_UVS out.uv = vertex.uv; #endif + #ifdef VERTEX_TANGENTS out.world_tangent = mesh_tangent_local_to_world(model, vertex.tangent); #endif + #ifdef VERTEX_COLORS out.color = vertex.color; #endif - out.clip_position = mesh_position_world_to_clip(out.world_position); return out; } diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index f27b4a5c5efe1..fe2c21544ee44 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -325,13 +325,24 @@ impl SpecializedMeshPipeline for Mesh2dPipeline { key: Self::Key, layout: &MeshVertexBufferLayout, ) -> Result { - let mut vertex_attributes = vec![ - Mesh::ATTRIBUTE_POSITION.at_shader_location(0), - Mesh::ATTRIBUTE_NORMAL.at_shader_location(1), - Mesh::ATTRIBUTE_UV_0.at_shader_location(2), - ]; - let mut shader_defs = Vec::new(); + let mut vertex_attributes = Vec::new(); + + if layout.contains(Mesh::ATTRIBUTE_POSITION) { + shader_defs.push(String::from("VERTEX_POSITIONS")); + vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0)); + } + + if layout.contains(Mesh::ATTRIBUTE_NORMAL) { + shader_defs.push(String::from("VERTEX_NORMALS")); + vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(1)); + } + + if layout.contains(Mesh::ATTRIBUTE_UV_0) { + shader_defs.push(String::from("VERTEX_UVS")); + vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(2)); + } + if layout.contains(Mesh::ATTRIBUTE_TANGENT) { shader_defs.push(String::from("VERTEX_TANGENTS")); vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(3)); diff --git a/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl b/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl index 5e5671eba7eff..95adaa22f85f9 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl +++ b/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl @@ -5,9 +5,15 @@ #import bevy_sprite::mesh2d_functions struct Vertex { +#ifdef VERTEX_POSITIONS @location(0) position: vec3, +#endif +#ifdef VERTEX_NORMALS @location(1) normal: vec3, +#endif +#ifdef VERTEX_UVS @location(2) uv: vec2, +#endif #ifdef VERTEX_TANGENTS @location(3) tangent: vec4, #endif @@ -24,13 +30,24 @@ struct VertexOutput { @vertex fn vertex(vertex: Vertex) -> VertexOutput { var out: VertexOutput; + +#ifdef VERTEX_UVS out.uv = vertex.uv; +#endif + +#ifdef VERTEX_POSITIONS out.world_position = mesh2d_position_local_to_world(mesh.model, vec4(vertex.position, 1.0)); out.clip_position = mesh2d_position_world_to_clip(out.world_position); +#endif + +#ifdef VERTEX_NORMALS out.world_normal = mesh2d_normal_local_to_world(vertex.normal); +#endif + #ifdef VERTEX_TANGENTS out.world_tangent = mesh2d_tangent_local_to_world(mesh.model, vertex.tangent); #endif + #ifdef VERTEX_COLORS out.color = vertex.color; #endif @@ -44,5 +61,9 @@ struct FragmentInput { @fragment fn fragment(in: FragmentInput) -> @location(0) vec4 { +#ifdef VERTEX_COLORS + return in.color; +#else return vec4(1.0, 0.0, 1.0, 1.0); +#endif }