Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Add support for vertex colors #4528

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ path = "examples/3d/parenting.rs"
name = "pbr"
path = "examples/3d/pbr.rs"

[[example]]
name = "render_to_texture"
path = "examples/3d/render_to_texture.rs"

[[example]]
name = "shadow_biases"
path = "examples/3d/shadow_biases.rs"
Expand All @@ -212,10 +216,6 @@ path = "examples/3d/spherical_area_lights.rs"
name = "texture"
path = "examples/3d/texture.rs"

[[example]]
name = "render_to_texture"
path = "examples/3d/render_to_texture.rs"

[[example]]
name = "two_passes"
path = "examples/3d/two_passes.rs"
Expand All @@ -224,6 +224,10 @@ path = "examples/3d/two_passes.rs"
name = "update_gltf_scene"
path = "examples/3d/update_gltf_scene.rs"

[[example]]
name = "vertex_colors"
path = "examples/3d/vertex_colors.rs"

[[example]]
name = "wireframe"
path = "examples/3d/wireframe.rs"
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,12 @@ async fn load_gltf<'a, 'b>(
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
}

// if let Some(vertex_attribute) = reader
// .read_colors(0)
// .map(|v| VertexAttributeValues::Float32x4(v.into_rgba_f32().collect()))
// {
// mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, vertex_attribute);
// }
if let Some(vertex_attribute) = reader
.read_colors(0)
.map(|v| VertexAttributeValues::Float32x4(v.into_rgba_f32().collect()))
{
mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, vertex_attribute);
}

if let Some(iter) = reader.read_joints(0) {
let vertex_attribute = VertexAttributeValues::Uint16x4(iter.into_u16().collect());
Expand Down
9 changes: 7 additions & 2 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,11 @@ impl SpecializedMeshPipeline for MeshPipeline {
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(3));
}

if layout.contains(Mesh::ATTRIBUTE_COLOR) {
shader_defs.push(String::from("VERTEX_COLORS"));
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(4));
}

// TODO: consider exposing this in shaders in a more generally useful way, such as:
// # if AVAILABLE_STORAGE_BUFFER_BINDINGS == 3
// /* use storage buffers here */
Expand All @@ -577,8 +582,8 @@ impl SpecializedMeshPipeline for MeshPipeline {
&& layout.contains(Mesh::ATTRIBUTE_JOINT_WEIGHT)
{
shader_defs.push(String::from("SKINNED"));
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_INDEX.at_shader_location(4));
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_WEIGHT.at_shader_location(5));
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_INDEX.at_shader_location(5));
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_WEIGHT.at_shader_location(6));
bind_group_layout.push(self.skinned_mesh_layout.clone());
} else {
bind_group_layout.push(self.mesh_layout.clone());
Expand Down
22 changes: 19 additions & 3 deletions crates/bevy_pbr/src/render/mesh.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ struct Vertex {
#ifdef VERTEX_TANGENTS
[[location(3)]] tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
#ifdef SKINNED
[[location(4)]] joint_indices: vec4<u32>;
[[location(5)]] joint_weights: vec4<f32>;
[[location(5)]] joint_indices: vec4<u32>;
[[location(6)]] joint_weights: vec4<f32>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I shifted the locations to match the ids given in the MeshVertexAttributes in bevy_render/src/mesh/mesh/mod.rs.

#endif
};

Expand All @@ -22,6 +25,9 @@ struct VertexOutput {
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
};

[[group(2), binding(0)]]
Expand Down Expand Up @@ -60,6 +66,9 @@ fn vertex(vertex: Vertex) -> VertexOutput {
);
#endif
#endif
#ifdef VERTEX_COLORS
out.color = vertex.color;
#endif

out.uv = vertex.uv;
out.clip_position = view.view_proj * out.world_position;
Expand All @@ -74,9 +83,16 @@ struct FragmentInput {
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
};

[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
#ifdef VERTEX_COLORS
return in.color;
#else
return vec4<f32>(1.0, 0.0, 1.0, 1.0);
}
#endif
}
6 changes: 6 additions & 0 deletions crates/bevy_pbr/src/render/pbr.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -465,11 +465,17 @@ struct FragmentInput {
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
};

[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
var output_color: vec4<f32> = material.base_color;
#ifdef VERTEX_COLORS
output_color = output_color * in.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);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/mesh/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl Mesh {

/// Per vertex coloring. Use in conjunction with [`Mesh::insert_attribute`]
pub const ATTRIBUTE_COLOR: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Color", 4, VertexFormat::Uint32);
MeshVertexAttribute::new("Vertex_Color", 4, VertexFormat::Float32x4);

/// Per vertex joint transform matrix weight. Use in conjunction with [`Mesh::insert_attribute`]
pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute =
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_sprite/src/mesh2d/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ impl SpecializedMeshPipeline for Mesh2dPipeline {
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(3));
}

if layout.contains(Mesh::ATTRIBUTE_COLOR) {
shader_defs.push(String::from("VERTEX_COLORS"));
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(4));
}

#[cfg(feature = "webgl")]
shader_defs.push(String::from("NO_ARRAY_TEXTURES_SUPPORT"));

Expand Down
7 changes: 5 additions & 2 deletions examples/2d/mesh2d_manual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bevy::{
prelude::*,
reflect::TypeUuid,
render::{
mesh::Indices,
mesh::{Indices, MeshVertexAttribute},
render_asset::RenderAssets,
render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline},
render_resource::{
Expand Down Expand Up @@ -72,7 +72,10 @@ fn star(
// And a RGB color attribute as well
let mut v_color: Vec<u32> = vec![Color::BLACK.as_linear_rgba_u32()];
v_color.extend_from_slice(&[Color::YELLOW.as_linear_rgba_u32(); 10]);
star.insert_attribute(Mesh::ATTRIBUTE_COLOR, v_color);
star.insert_attribute(
MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
v_color,
);

// Now, we specify the indices of the vertex that are going to compose the
// triangles in our star. Vertices in triangles have to be specified in CCW
Expand Down
59 changes: 59 additions & 0 deletions examples/3d/vertex_colors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use bevy::{prelude::*, render::mesh::VertexAttributeValues};

fn main() {
App::new()
.insert_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.run();
}

/// set up a simple 3D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// plane
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..default()
});
// cube
// Assign vertex colors based on vertex positions
let mut colorful_cube = Mesh::from(shape::Cube { size: 1.0 });
if let Some(VertexAttributeValues::Float32x3(positions)) =
colorful_cube.attribute(Mesh::ATTRIBUTE_POSITION)
{
let colors: Vec<[f32; 4]> = positions
.iter()
.map(|[r, g, b]| [(1. - *r) / 2., (1. - *g) / 2., (1. - *b) / 2., 1.])
.collect();
colorful_cube.insert_attribute(Mesh::ATTRIBUTE_COLOR, colors);
}
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(colorful_cube),
// This is the default color, but note that vertex colors are
// multiplied by the base color, so you'll likely want this to be
// white if using vertex colors.
material: materials.add(Color::rgb(1., 1., 1.).into()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It defaults to white, as I recall, to allow default to be identity for a material with a texture. That said, I think it's good to comment as it could easily be a source of confusion otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 37 - 40 are really there just to explain why the base_color should probably be white when using vertex colors. It seemed like a good way to document this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it is. And it's an additional flexibility to be able to tint things, if nothing else. :)

transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
// light
commands.spawn_bundle(PointLightBundle {
point_light: PointLight {
intensity: 1500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// camera
commands.spawn_bundle(PerspectiveCameraBundle {
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Example | File | Description
`spherical_area_lights` | [`3d/spherical_area_lights.rs`](./3d/spherical_area_lights.rs) | Demonstrates how point light radius values affect light behavior.
`texture` | [`3d/texture.rs`](./3d/texture.rs) | Shows configuration of texture materials
`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
`vertex_colors` | [`3d/vertex_colors.rs`](./3d/vertex_colors.rs) | Shows the use of vertex colors
`wireframe` | [`3d/wireframe.rs`](./3d/wireframe.rs) | Showcases wireframe rendering

## Animation
Expand Down