From 50fdff677e2c2afa6eadb3eab79aed29468bf099 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 25 Nov 2021 15:47:59 +0100 Subject: [PATCH 1/2] added Vertex_Color support to bevy_pbr2 --- Cargo.toml | 4 + examples/3d/pbr_colors_pipelined.rs | 83 ++++++++++++++ examples/README.md | 1 + pipelined/bevy_pbr2/src/render/mesh.rs | 116 ++++++++++---------- pipelined/bevy_pbr2/src/render/mesh.wgsl | 29 ++++- pipelined/bevy_pbr2/src/render/mod.rs | 3 + pipelined/bevy_pbr2/src/render/pbr.wgsl | 12 ++ pipelined/bevy_render2/src/mesh/mesh/mod.rs | 2 + 8 files changed, 193 insertions(+), 57 deletions(-) create mode 100644 examples/3d/pbr_colors_pipelined.rs diff --git a/Cargo.toml b/Cargo.toml index 6b5267be70da8..4350d48298779 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -201,6 +201,10 @@ path = "examples/3d/pbr.rs" name = "pbr_pipelined" path = "examples/3d/pbr_pipelined.rs" +[[example]] +name = "pbr_colors_pipelined" +path = "examples/3d/pbr_colors_pipelined.rs" + [[example]] name = "render_to_texture" path = "examples/3d/render_to_texture.rs" diff --git a/examples/3d/pbr_colors_pipelined.rs b/examples/3d/pbr_colors_pipelined.rs new file mode 100644 index 0000000000000..34a3929f09f76 --- /dev/null +++ b/examples/3d/pbr_colors_pipelined.rs @@ -0,0 +1,83 @@ +use bevy::{ + math::Vec3, + pbr2::{PbrBundle, PointLightBundle, StandardMaterial}, + prelude::{App, Assets, Commands, ResMut, Transform}, + render2::{ + camera::PerspectiveCameraBundle, + mesh::{shape, Mesh, VertexAttributeValues}, + }, + PipelinedDefaultPlugins, +}; + +/// This example illustrates how to use the vertex colors attribute. +fn main() { + App::new() + .add_plugins(PipelinedDefaultPlugins) + .add_startup_system(setup) + .run(); +} + +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + // create a generic cube + let mut cube_with_colors = Mesh::from(shape::Cube { size: 2.0 }); + + // set some nice nice colors! + cube_with_colors.set_attribute( + Mesh::ATTRIBUTE_COLOR, + // NOTE: the attribute count has to be consistent across all attributes, otherwise bevy + // will panic. + VertexAttributeValues::from(vec![ + // top + [0.79, 0.73, 0.07, 1.], + [0.74, 0.14, 0.29, 1.], + [0.08, 0.55, 0.74, 1.], + [0.20, 0.27, 0.29, 1.], + // bottom + [0.79, 0.73, 0.07, 1.], + [0.74, 0.14, 0.29, 1.], + [0.08, 0.55, 0.74, 1.], + [0.20, 0.27, 0.29, 1.], + // right + [0.79, 0.73, 0.07, 1.], + [0.74, 0.14, 0.29, 1.], + [0.08, 0.55, 0.74, 1.], + [0.20, 0.27, 0.29, 1.], + // left + [0.79, 0.73, 0.07, 1.], + [0.74, 0.14, 0.29, 1.], + [0.08, 0.55, 0.74, 1.], + [0.20, 0.27, 0.29, 1.], + // front + [0.79, 0.73, 0.07, 1.], + [0.74, 0.14, 0.29, 1.], + [0.08, 0.55, 0.74, 1.], + [0.20, 0.27, 0.29, 1.], + // back + [0.79, 0.73, 0.07, 1.], + [0.74, 0.14, 0.29, 1.], + [0.08, 0.55, 0.74, 1.], + [0.20, 0.27, 0.29, 1.], + ]), + ); + // cube + commands.spawn_bundle(PbrBundle { + mesh: meshes.add(cube_with_colors), // use our cube with vertex colors + material: materials.add(Default::default()), + transform: Transform::from_xyz(0.0, 0.0, 0.0), + ..Default::default() + }); + // light + commands.spawn_bundle(PointLightBundle { + transform: Transform::from_xyz(4.0, 8.0, 4.0), + ..Default::default() + }); + // camera + commands.spawn_bundle(PerspectiveCameraBundle { + transform: Transform::from_xyz(3.0, 5.0, -8.0).looking_at(Vec3::ZERO, Vec3::Y), + ..Default::default() + }); +} diff --git a/examples/README.md b/examples/README.md index 6d8a563bd8fb6..2ba09336e5d96 100644 --- a/examples/README.md +++ b/examples/README.md @@ -118,6 +118,7 @@ Example | File | Description `update_gltf_scene` | [`3d/update_gltf_scene.rs`](./3d/update_gltf_scene.rs) | Update a scene from a gltf file, either by spawning the scene as a child of another entity, or by accessing the entities of the scene `wireframe` | [`3d/wireframe.rs`](./3d/wireframe.rs) | Showcases wireframe rendering `z_sort_debug` | [`3d/z_sort_debug.rs`](./3d/z_sort_debug.rs) | Visualizes camera Z-ordering +`pbr_colors_pipelined` | [`3d/pbr_colors_pipelined.rs`](./3d/pbr_colors_pipelined.rs) | PBR rendering with custom vertex colors ## Application diff --git a/pipelined/bevy_pbr2/src/render/mesh.rs b/pipelined/bevy_pbr2/src/render/mesh.rs index 567745f919e0f..a805922ee784c 100644 --- a/pipelined/bevy_pbr2/src/render/mesh.rs +++ b/pipelined/bevy_pbr2/src/render/mesh.rs @@ -329,6 +329,7 @@ bitflags::bitflags! { const NONE = 0; const VERTEX_TANGENTS = (1 << 0); const TRANSPARENT_MAIN_PASS = (1 << 1); + const VERTEX_COLORS = (1 << 2); const MSAA_RESERVED_BITS = MeshPipelineKey::MSAA_MASK_BITS << MeshPipelineKey::MSAA_SHIFT_BITS; } } @@ -351,66 +352,69 @@ impl SpecializedPipeline for MeshPipeline { type Key = MeshPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let (vertex_array_stride, vertex_attributes) = - if key.contains(MeshPipelineKey::VERTEX_TANGENTS) { - ( - 48, - vec![ - // Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically)) - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 12, - shader_location: 0, - }, - // Normal - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 0, - shader_location: 1, - }, - // Uv (GOTCHA! uv is no longer third in the buffer due to how Mesh sorts attributes (alphabetically)) - VertexAttribute { - format: VertexFormat::Float32x2, - offset: 40, - shader_location: 2, - }, - // Tangent - VertexAttribute { - format: VertexFormat::Float32x4, - offset: 24, - shader_location: 3, - }, - ], - ) - } else { - ( - 32, - vec![ - // Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically)) - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 12, - shader_location: 0, - }, - // Normal - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 0, - shader_location: 1, - }, - // Uv - VertexAttribute { - format: VertexFormat::Float32x2, - offset: 24, - shader_location: 2, - }, - ], - ) - }; + let mut vertex_attributes: Vec = vec![]; + let mut offset = 0; + + // Mesh attributes are sorted alphabetically in the buffer, so add them in the correct + // order. + + // colors: will be at location 3 or 4 depending on wether Vertex_Tangents are used + if key.contains(MeshPipelineKey::VERTEX_COLORS) { + vertex_attributes.push(VertexAttribute { + format: VertexFormat::Float32x4, + offset, + shader_location: if key.contains(MeshPipelineKey::VERTEX_TANGENTS) { + 4 + } else { + 3 + }, + }); + offset += 16; + } + + // normals + vertex_attributes.push(VertexAttribute { + format: VertexFormat::Float32x3, + offset, + shader_location: 1, + }); + offset += 12; + + // positions + vertex_attributes.push(VertexAttribute { + format: VertexFormat::Float32x3, + offset, + shader_location: 0, + }); + offset += 12; + + // tangents + if key.contains(MeshPipelineKey::VERTEX_TANGENTS) { + vertex_attributes.push(VertexAttribute { + format: VertexFormat::Float32x4, + offset, + shader_location: 3, + }); + offset += 16; + } + + // uvs + vertex_attributes.push(VertexAttribute { + format: VertexFormat::Float32x2, + offset, + shader_location: 2, + }); + offset += 8; + + let vertex_array_stride = offset; + let mut shader_defs = Vec::new(); if key.contains(MeshPipelineKey::VERTEX_TANGENTS) { shader_defs.push(String::from("VERTEX_TANGENTS")); } + if key.contains(MeshPipelineKey::VERTEX_COLORS) { + shader_defs.push(String::from("VERTEX_COLORS")); + } let (label, blend, depth_write_enabled); if key.contains(MeshPipelineKey::TRANSPARENT_MAIN_PASS) { diff --git a/pipelined/bevy_pbr2/src/render/mesh.wgsl b/pipelined/bevy_pbr2/src/render/mesh.wgsl index 0bb20aeea0e62..8a4f6e3ec4f72 100644 --- a/pipelined/bevy_pbr2/src/render/mesh.wgsl +++ b/pipelined/bevy_pbr2/src/render/mesh.wgsl @@ -8,6 +8,14 @@ struct Vertex { #ifdef VERTEX_TANGENTS [[location(3)]] tangent: vec4; #endif +#ifdef VERTEX_COLORS +#ifdef VERTEX_TANGENTS + [[location(4)]] color: vec4; +#endif +#ifndef VERTEX_TANGENTS + [[location(3)]] color: vec4; +#endif +#endif }; struct VertexOutput { @@ -18,6 +26,14 @@ struct VertexOutput { #ifdef VERTEX_TANGENTS [[location(3)]] world_tangent: vec4; #endif +#ifdef VERTEX_COLORS +#ifdef VERTEX_TANGENTS + [[location(4)]] world_color: vec4; +#endif +#ifndef VERTEX_TANGENTS + [[location(3)]] world_color: vec4; +#endif +#endif }; [[group(2), binding(0)]] @@ -45,6 +61,9 @@ fn vertex(vertex: Vertex) -> VertexOutput { ) * vertex.tangent.xyz, vertex.tangent.w ); +#endif +#ifdef VERTEX_COLORS + out.world_color = vertex.color; #endif return out; } @@ -57,9 +76,17 @@ struct FragmentInput { #ifdef VERTEX_TANGENTS [[location(3)]] world_tangent: vec4; #endif +#ifdef VERTEX_COLORS +#ifdef VERTEX_TANGENTS + [[location(4)]] world_color: vec4; +#endif +#ifndef VERTEX_TANGENTS + [[location(3)]] world_color: vec4; +#endif +#endif }; [[stage(fragment)]] fn fragment(in: FragmentInput) -> [[location(0)]] vec4 { return vec4(1.0, 0.0, 1.0, 1.0); -} \ No newline at end of file +} diff --git a/pipelined/bevy_pbr2/src/render/mod.rs b/pipelined/bevy_pbr2/src/render/mod.rs index 348f7db955280..077520ab77996 100644 --- a/pipelined/bevy_pbr2/src/render/mod.rs +++ b/pipelined/bevy_pbr2/src/render/mod.rs @@ -260,6 +260,9 @@ pub fn queue_meshes( if mesh.has_tangents { pbr_key.mesh_key |= MeshPipelineKey::VERTEX_TANGENTS; } + if mesh.has_colors { + pbr_key.mesh_key |= MeshPipelineKey::VERTEX_COLORS; + } } if let AlphaMode::Blend = material.alpha_mode { diff --git a/pipelined/bevy_pbr2/src/render/pbr.wgsl b/pipelined/bevy_pbr2/src/render/pbr.wgsl index bb5515657a1f4..cff79388cee49 100644 --- a/pipelined/bevy_pbr2/src/render/pbr.wgsl +++ b/pipelined/bevy_pbr2/src/render/pbr.wgsl @@ -396,11 +396,23 @@ struct FragmentInput { #ifdef VERTEX_TANGENTS [[location(3)]] world_tangent: vec4; #endif +#ifdef VERTEX_COLORS +#ifdef VERTEX_TANGENTS + [[location(4)]] world_color: vec4; +#endif +#ifndef VERTEX_TANGENTS + [[location(3)]] world_color: vec4; +#endif +#endif }; [[stage(fragment)]] fn fragment(in: FragmentInput) -> [[location(0)]] vec4 { var output_color: vec4 = material.base_color; + +#ifdef VERTEX_COLORS + output_color = in.world_color; +#endif if ((material.flags & STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) { output_color = output_color * textureSample(base_color_texture, base_color_sampler, in.uv); } diff --git a/pipelined/bevy_render2/src/mesh/mesh/mod.rs b/pipelined/bevy_render2/src/mesh/mesh/mod.rs index 57614f378e34a..cd88263aa2dcf 100644 --- a/pipelined/bevy_render2/src/mesh/mesh/mod.rs +++ b/pipelined/bevy_render2/src/mesh/mesh/mod.rs @@ -593,6 +593,7 @@ pub struct GpuMesh { pub vertex_buffer: Buffer, pub index_info: Option, pub has_tangents: bool, + pub has_colors: bool, } /// The index info of a [`GpuMesh`]. @@ -640,6 +641,7 @@ impl RenderAsset for Mesh { vertex_buffer, index_info, has_tangents: mesh.attributes.contains_key(Mesh::ATTRIBUTE_TANGENT), + has_colors: mesh.attributes.contains_key(Mesh::ATTRIBUTE_COLOR), }) } } From 8fdbf896e8ba72eb842f10d8f3eab85d978cb5d0 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 9 Dec 2021 08:48:02 +0100 Subject: [PATCH 2/2] refactor: use #else in wgsl --- pipelined/bevy_pbr2/src/render/mesh.wgsl | 6 ++---- pipelined/bevy_pbr2/src/render/pbr.wgsl | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pipelined/bevy_pbr2/src/render/mesh.wgsl b/pipelined/bevy_pbr2/src/render/mesh.wgsl index 8a4f6e3ec4f72..d382dab3217bc 100644 --- a/pipelined/bevy_pbr2/src/render/mesh.wgsl +++ b/pipelined/bevy_pbr2/src/render/mesh.wgsl @@ -11,8 +11,7 @@ struct Vertex { #ifdef VERTEX_COLORS #ifdef VERTEX_TANGENTS [[location(4)]] color: vec4; -#endif -#ifndef VERTEX_TANGENTS +#else [[location(3)]] color: vec4; #endif #endif @@ -29,8 +28,7 @@ struct VertexOutput { #ifdef VERTEX_COLORS #ifdef VERTEX_TANGENTS [[location(4)]] world_color: vec4; -#endif -#ifndef VERTEX_TANGENTS +#else [[location(3)]] world_color: vec4; #endif #endif diff --git a/pipelined/bevy_pbr2/src/render/pbr.wgsl b/pipelined/bevy_pbr2/src/render/pbr.wgsl index ae9696ebd80c4..bb2c12c633a19 100644 --- a/pipelined/bevy_pbr2/src/render/pbr.wgsl +++ b/pipelined/bevy_pbr2/src/render/pbr.wgsl @@ -435,8 +435,7 @@ struct FragmentInput { #ifdef VERTEX_COLORS #ifdef VERTEX_TANGENTS [[location(4)]] world_color: vec4; -#endif -#ifndef VERTEX_TANGENTS +#else [[location(3)]] world_color: vec4; #endif #endif