From a6eb3fa6d68bb4a70c9c50927b41a70b894a7c50 Mon Sep 17 00:00:00 2001 From: "Herbert \"TheBracket" Date: Mon, 30 May 2022 16:59:45 +0000 Subject: [PATCH] Apply vertex colors to ColorMaterial and Mesh2D (#4812) # Objective - Add Vertex Color support to 2D meshes and ColorMaterial. This extends the work from #4528 (which in turn builds on the excellent tangent handling). ## Solution - Added `#ifdef` wrapped support for vertex colors in the 2D mesh shader and `ColorMaterial` shader. - Added an example, `mesh2d_vertex_color_texture` to demonstrate it in action. ![image](https://user-images.githubusercontent.com/14896751/169530930-6ae0c6be-2f69-40e3-a600-ba91d7178bc3.png) --- ## Changelog - Added optional (ifdef wrapped) vertex color support to the 2dmesh and color material systems. --- Cargo.toml | 4 ++ .../src/mesh2d/color_material.wgsl | 7 ++++ crates/bevy_sprite/src/mesh2d/mesh2d.wgsl | 9 +++++ examples/2d/mesh2d_vertex_color_texture.rs | 40 +++++++++++++++++++ examples/README.md | 1 + 5 files changed, 61 insertions(+) create mode 100644 examples/2d/mesh2d_vertex_color_texture.rs diff --git a/Cargo.toml b/Cargo.toml index 4dfe5fc8c7119..97e1e90b41e51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,6 +143,10 @@ path = "examples/2d/mesh2d.rs" name = "mesh2d_manual" path = "examples/2d/mesh2d_manual.rs" +[[example]] +name = "mesh2d_vertex_color_texture" +path = "examples/2d/mesh2d_vertex_color_texture.rs" + [[example]] name = "shapes" path = "examples/2d/shapes.rs" diff --git a/crates/bevy_sprite/src/mesh2d/color_material.wgsl b/crates/bevy_sprite/src/mesh2d/color_material.wgsl index a11e48094f3c6..dac272b09686e 100644 --- a/crates/bevy_sprite/src/mesh2d/color_material.wgsl +++ b/crates/bevy_sprite/src/mesh2d/color_material.wgsl @@ -29,13 +29,20 @@ struct FragmentInput { #ifdef VERTEX_TANGENTS [[location(3)]] world_tangent: vec4; #endif +#ifdef VERTEX_COLORS + [[location(4)]] colors: vec4; +#endif }; [[stage(fragment)]] fn fragment(in: FragmentInput) -> [[location(0)]] vec4 { var output_color: vec4 = material.color; if ((material.flags & COLOR_MATERIAL_FLAGS_TEXTURE_BIT) != 0u) { +#ifdef VERTEX_COLORS + output_color = output_color * textureSample(texture, texture_sampler, in.uv) * in.colors; +#else output_color = output_color * textureSample(texture, texture_sampler, in.uv); +#endif } return output_color; } \ No newline at end of file diff --git a/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl b/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl index 1e2b02eb64811..4766c5cf7fb26 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl +++ b/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl @@ -8,6 +8,9 @@ struct Vertex { #ifdef VERTEX_TANGENTS [[location(3)]] tangent: vec4; #endif +#ifdef VERTEX_COLORS + [[location(4)]] colors: vec4; +#endif }; struct VertexOutput { @@ -18,6 +21,9 @@ struct VertexOutput { #ifdef VERTEX_TANGENTS [[location(3)]] world_tangent: vec4; #endif +#ifdef VERTEX_COLORS + [[location(4)]] colors: vec4; +#endif }; [[group(0), binding(0)]] @@ -48,6 +54,9 @@ fn vertex(vertex: Vertex) -> VertexOutput { ) * vertex.tangent.xyz, vertex.tangent.w ); +#endif +#ifdef VERTEX_COLORS + out.colors = vertex.colors; #endif return out; } diff --git a/examples/2d/mesh2d_vertex_color_texture.rs b/examples/2d/mesh2d_vertex_color_texture.rs new file mode 100644 index 0000000000000..598a1e54d7f83 --- /dev/null +++ b/examples/2d/mesh2d_vertex_color_texture.rs @@ -0,0 +1,40 @@ +//! Shows how to render a polygonal [`Mesh`], generated from a [`Quad`] primitive, in a 2D scene. +//! Adds a texture and colored vertices, giving per-vertex tinting. + +use bevy::{prelude::*, sprite::MaterialMesh2dBundle}; + +fn main() { + App::new() + .add_plugins(DefaultPlugins) + .add_startup_system(setup) + .run(); +} + +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, + asset_server: Res, +) { + // Load the Bevy logo as a texture + let texture_handle = asset_server.load("branding/banner.png"); + // Build a default quad mesh + let mut mesh = Mesh::from(shape::Quad::default()); + // Build vertex colors for the quad. One entry per vertex (the corners of the quad) + let vertex_colors: Vec<[f32; 4]> = vec![ + Color::RED.as_rgba_f32(), + Color::GREEN.as_rgba_f32(), + Color::BLUE.as_rgba_f32(), + Color::WHITE.as_rgba_f32(), + ]; + // Insert the vertex colors as an attribute + mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, vertex_colors); + // Spawn + commands.spawn_bundle(OrthographicCameraBundle::new_2d()); + commands.spawn_bundle(MaterialMesh2dBundle { + mesh: meshes.add(mesh).into(), + transform: Transform::default().with_scale(Vec3::splat(128.)), + material: materials.add(ColorMaterial::from(texture_handle)), + ..default() + }); +} diff --git a/examples/README.md b/examples/README.md index 8113cc818201e..e80f3caa324f0 100644 --- a/examples/README.md +++ b/examples/README.md @@ -89,6 +89,7 @@ Example | File | Description `move_sprite` | [`2d/move_sprite.rs`](./2d/move_sprite.rs) | Changes the transform of a sprite. `mesh2d` | [`2d/mesh2d.rs`](./2d/mesh2d.rs) | Renders a 2d mesh `mesh2d_manual` | [`2d/mesh2d_manual.rs`](./2d/mesh2d_manual.rs) | Renders a custom mesh "manually" with "mid-level" renderer apis. +`mesh2d_vertex_color_texture` | [`2d/mesh2d_vertex_color_texture.rs`](./2d/mesh2d_vertex_color_texture.rs) | Renders a 2d mesh with vertex color attributes. `shapes` | [`2d/shapes.rs`](./2d/shapes.rs) | Renders a rectangle, circle, and hexagon `sprite` | [`2d/sprite.rs`](./2d/sprite.rs) | Renders a sprite `sprite_sheet` | [`2d/sprite_sheet.rs`](./2d/sprite_sheet.rs) | Renders an animated sprite