Skip to content

Commit 50fdff6

Browse files
committed
added Vertex_Color support to bevy_pbr2
1 parent 0bf90bb commit 50fdff6

File tree

8 files changed

+193
-57
lines changed

8 files changed

+193
-57
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ path = "examples/3d/pbr.rs"
201201
name = "pbr_pipelined"
202202
path = "examples/3d/pbr_pipelined.rs"
203203

204+
[[example]]
205+
name = "pbr_colors_pipelined"
206+
path = "examples/3d/pbr_colors_pipelined.rs"
207+
204208
[[example]]
205209
name = "render_to_texture"
206210
path = "examples/3d/render_to_texture.rs"

examples/3d/pbr_colors_pipelined.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use bevy::{
2+
math::Vec3,
3+
pbr2::{PbrBundle, PointLightBundle, StandardMaterial},
4+
prelude::{App, Assets, Commands, ResMut, Transform},
5+
render2::{
6+
camera::PerspectiveCameraBundle,
7+
mesh::{shape, Mesh, VertexAttributeValues},
8+
},
9+
PipelinedDefaultPlugins,
10+
};
11+
12+
/// This example illustrates how to use the vertex colors attribute.
13+
fn main() {
14+
App::new()
15+
.add_plugins(PipelinedDefaultPlugins)
16+
.add_startup_system(setup)
17+
.run();
18+
}
19+
20+
fn setup(
21+
mut commands: Commands,
22+
mut meshes: ResMut<Assets<Mesh>>,
23+
mut materials: ResMut<Assets<StandardMaterial>>,
24+
) {
25+
// create a generic cube
26+
let mut cube_with_colors = Mesh::from(shape::Cube { size: 2.0 });
27+
28+
// set some nice nice colors!
29+
cube_with_colors.set_attribute(
30+
Mesh::ATTRIBUTE_COLOR,
31+
// NOTE: the attribute count has to be consistent across all attributes, otherwise bevy
32+
// will panic.
33+
VertexAttributeValues::from(vec![
34+
// top
35+
[0.79, 0.73, 0.07, 1.],
36+
[0.74, 0.14, 0.29, 1.],
37+
[0.08, 0.55, 0.74, 1.],
38+
[0.20, 0.27, 0.29, 1.],
39+
// bottom
40+
[0.79, 0.73, 0.07, 1.],
41+
[0.74, 0.14, 0.29, 1.],
42+
[0.08, 0.55, 0.74, 1.],
43+
[0.20, 0.27, 0.29, 1.],
44+
// right
45+
[0.79, 0.73, 0.07, 1.],
46+
[0.74, 0.14, 0.29, 1.],
47+
[0.08, 0.55, 0.74, 1.],
48+
[0.20, 0.27, 0.29, 1.],
49+
// left
50+
[0.79, 0.73, 0.07, 1.],
51+
[0.74, 0.14, 0.29, 1.],
52+
[0.08, 0.55, 0.74, 1.],
53+
[0.20, 0.27, 0.29, 1.],
54+
// front
55+
[0.79, 0.73, 0.07, 1.],
56+
[0.74, 0.14, 0.29, 1.],
57+
[0.08, 0.55, 0.74, 1.],
58+
[0.20, 0.27, 0.29, 1.],
59+
// back
60+
[0.79, 0.73, 0.07, 1.],
61+
[0.74, 0.14, 0.29, 1.],
62+
[0.08, 0.55, 0.74, 1.],
63+
[0.20, 0.27, 0.29, 1.],
64+
]),
65+
);
66+
// cube
67+
commands.spawn_bundle(PbrBundle {
68+
mesh: meshes.add(cube_with_colors), // use our cube with vertex colors
69+
material: materials.add(Default::default()),
70+
transform: Transform::from_xyz(0.0, 0.0, 0.0),
71+
..Default::default()
72+
});
73+
// light
74+
commands.spawn_bundle(PointLightBundle {
75+
transform: Transform::from_xyz(4.0, 8.0, 4.0),
76+
..Default::default()
77+
});
78+
// camera
79+
commands.spawn_bundle(PerspectiveCameraBundle {
80+
transform: Transform::from_xyz(3.0, 5.0, -8.0).looking_at(Vec3::ZERO, Vec3::Y),
81+
..Default::default()
82+
});
83+
}

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ Example | File | Description
118118
`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
119119
`wireframe` | [`3d/wireframe.rs`](./3d/wireframe.rs) | Showcases wireframe rendering
120120
`z_sort_debug` | [`3d/z_sort_debug.rs`](./3d/z_sort_debug.rs) | Visualizes camera Z-ordering
121+
`pbr_colors_pipelined` | [`3d/pbr_colors_pipelined.rs`](./3d/pbr_colors_pipelined.rs) | PBR rendering with custom vertex colors
121122

122123
## Application
123124

pipelined/bevy_pbr2/src/render/mesh.rs

Lines changed: 60 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ bitflags::bitflags! {
329329
const NONE = 0;
330330
const VERTEX_TANGENTS = (1 << 0);
331331
const TRANSPARENT_MAIN_PASS = (1 << 1);
332+
const VERTEX_COLORS = (1 << 2);
332333
const MSAA_RESERVED_BITS = MeshPipelineKey::MSAA_MASK_BITS << MeshPipelineKey::MSAA_SHIFT_BITS;
333334
}
334335
}
@@ -351,66 +352,69 @@ impl SpecializedPipeline for MeshPipeline {
351352
type Key = MeshPipelineKey;
352353

353354
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
354-
let (vertex_array_stride, vertex_attributes) =
355-
if key.contains(MeshPipelineKey::VERTEX_TANGENTS) {
356-
(
357-
48,
358-
vec![
359-
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
360-
VertexAttribute {
361-
format: VertexFormat::Float32x3,
362-
offset: 12,
363-
shader_location: 0,
364-
},
365-
// Normal
366-
VertexAttribute {
367-
format: VertexFormat::Float32x3,
368-
offset: 0,
369-
shader_location: 1,
370-
},
371-
// Uv (GOTCHA! uv is no longer third in the buffer due to how Mesh sorts attributes (alphabetically))
372-
VertexAttribute {
373-
format: VertexFormat::Float32x2,
374-
offset: 40,
375-
shader_location: 2,
376-
},
377-
// Tangent
378-
VertexAttribute {
379-
format: VertexFormat::Float32x4,
380-
offset: 24,
381-
shader_location: 3,
382-
},
383-
],
384-
)
385-
} else {
386-
(
387-
32,
388-
vec![
389-
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
390-
VertexAttribute {
391-
format: VertexFormat::Float32x3,
392-
offset: 12,
393-
shader_location: 0,
394-
},
395-
// Normal
396-
VertexAttribute {
397-
format: VertexFormat::Float32x3,
398-
offset: 0,
399-
shader_location: 1,
400-
},
401-
// Uv
402-
VertexAttribute {
403-
format: VertexFormat::Float32x2,
404-
offset: 24,
405-
shader_location: 2,
406-
},
407-
],
408-
)
409-
};
355+
let mut vertex_attributes: Vec<VertexAttribute> = vec![];
356+
let mut offset = 0;
357+
358+
// Mesh attributes are sorted alphabetically in the buffer, so add them in the correct
359+
// order.
360+
361+
// colors: will be at location 3 or 4 depending on wether Vertex_Tangents are used
362+
if key.contains(MeshPipelineKey::VERTEX_COLORS) {
363+
vertex_attributes.push(VertexAttribute {
364+
format: VertexFormat::Float32x4,
365+
offset,
366+
shader_location: if key.contains(MeshPipelineKey::VERTEX_TANGENTS) {
367+
4
368+
} else {
369+
3
370+
},
371+
});
372+
offset += 16;
373+
}
374+
375+
// normals
376+
vertex_attributes.push(VertexAttribute {
377+
format: VertexFormat::Float32x3,
378+
offset,
379+
shader_location: 1,
380+
});
381+
offset += 12;
382+
383+
// positions
384+
vertex_attributes.push(VertexAttribute {
385+
format: VertexFormat::Float32x3,
386+
offset,
387+
shader_location: 0,
388+
});
389+
offset += 12;
390+
391+
// tangents
392+
if key.contains(MeshPipelineKey::VERTEX_TANGENTS) {
393+
vertex_attributes.push(VertexAttribute {
394+
format: VertexFormat::Float32x4,
395+
offset,
396+
shader_location: 3,
397+
});
398+
offset += 16;
399+
}
400+
401+
// uvs
402+
vertex_attributes.push(VertexAttribute {
403+
format: VertexFormat::Float32x2,
404+
offset,
405+
shader_location: 2,
406+
});
407+
offset += 8;
408+
409+
let vertex_array_stride = offset;
410+
410411
let mut shader_defs = Vec::new();
411412
if key.contains(MeshPipelineKey::VERTEX_TANGENTS) {
412413
shader_defs.push(String::from("VERTEX_TANGENTS"));
413414
}
415+
if key.contains(MeshPipelineKey::VERTEX_COLORS) {
416+
shader_defs.push(String::from("VERTEX_COLORS"));
417+
}
414418

415419
let (label, blend, depth_write_enabled);
416420
if key.contains(MeshPipelineKey::TRANSPARENT_MAIN_PASS) {

pipelined/bevy_pbr2/src/render/mesh.wgsl

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ struct Vertex {
88
#ifdef VERTEX_TANGENTS
99
[[location(3)]] tangent: vec4<f32>;
1010
#endif
11+
#ifdef VERTEX_COLORS
12+
#ifdef VERTEX_TANGENTS
13+
[[location(4)]] color: vec4<f32>;
14+
#endif
15+
#ifndef VERTEX_TANGENTS
16+
[[location(3)]] color: vec4<f32>;
17+
#endif
18+
#endif
1119
};
1220

1321
struct VertexOutput {
@@ -18,6 +26,14 @@ struct VertexOutput {
1826
#ifdef VERTEX_TANGENTS
1927
[[location(3)]] world_tangent: vec4<f32>;
2028
#endif
29+
#ifdef VERTEX_COLORS
30+
#ifdef VERTEX_TANGENTS
31+
[[location(4)]] world_color: vec4<f32>;
32+
#endif
33+
#ifndef VERTEX_TANGENTS
34+
[[location(3)]] world_color: vec4<f32>;
35+
#endif
36+
#endif
2137
};
2238

2339
[[group(2), binding(0)]]
@@ -45,6 +61,9 @@ fn vertex(vertex: Vertex) -> VertexOutput {
4561
) * vertex.tangent.xyz,
4662
vertex.tangent.w
4763
);
64+
#endif
65+
#ifdef VERTEX_COLORS
66+
out.world_color = vertex.color;
4867
#endif
4968
return out;
5069
}
@@ -57,9 +76,17 @@ struct FragmentInput {
5776
#ifdef VERTEX_TANGENTS
5877
[[location(3)]] world_tangent: vec4<f32>;
5978
#endif
79+
#ifdef VERTEX_COLORS
80+
#ifdef VERTEX_TANGENTS
81+
[[location(4)]] world_color: vec4<f32>;
82+
#endif
83+
#ifndef VERTEX_TANGENTS
84+
[[location(3)]] world_color: vec4<f32>;
85+
#endif
86+
#endif
6087
};
6188

6289
[[stage(fragment)]]
6390
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
6491
return vec4<f32>(1.0, 0.0, 1.0, 1.0);
65-
}
92+
}

pipelined/bevy_pbr2/src/render/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ pub fn queue_meshes(
260260
if mesh.has_tangents {
261261
pbr_key.mesh_key |= MeshPipelineKey::VERTEX_TANGENTS;
262262
}
263+
if mesh.has_colors {
264+
pbr_key.mesh_key |= MeshPipelineKey::VERTEX_COLORS;
265+
}
263266
}
264267

265268
if let AlphaMode::Blend = material.alpha_mode {

pipelined/bevy_pbr2/src/render/pbr.wgsl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,11 +396,23 @@ struct FragmentInput {
396396
#ifdef VERTEX_TANGENTS
397397
[[location(3)]] world_tangent: vec4<f32>;
398398
#endif
399+
#ifdef VERTEX_COLORS
400+
#ifdef VERTEX_TANGENTS
401+
[[location(4)]] world_color: vec4<f32>;
402+
#endif
403+
#ifndef VERTEX_TANGENTS
404+
[[location(3)]] world_color: vec4<f32>;
405+
#endif
406+
#endif
399407
};
400408

401409
[[stage(fragment)]]
402410
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
403411
var output_color: vec4<f32> = material.base_color;
412+
413+
#ifdef VERTEX_COLORS
414+
output_color = in.world_color;
415+
#endif
404416
if ((material.flags & STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) {
405417
output_color = output_color * textureSample(base_color_texture, base_color_sampler, in.uv);
406418
}

pipelined/bevy_render2/src/mesh/mesh/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ pub struct GpuMesh {
593593
pub vertex_buffer: Buffer,
594594
pub index_info: Option<GpuIndexInfo>,
595595
pub has_tangents: bool,
596+
pub has_colors: bool,
596597
}
597598

598599
/// The index info of a [`GpuMesh`].
@@ -640,6 +641,7 @@ impl RenderAsset for Mesh {
640641
vertex_buffer,
641642
index_info,
642643
has_tangents: mesh.attributes.contains_key(Mesh::ATTRIBUTE_TANGENT),
644+
has_colors: mesh.attributes.contains_key(Mesh::ATTRIBUTE_COLOR),
643645
})
644646
}
645647
}

0 commit comments

Comments
 (0)