1use bevy::{
4 asset::RenderAssetUsages,
5 mesh::{Indices, PrimitiveTopology},
6 prelude::*,
7 reflect::TypePath,
8 render::render_resource::AsBindGroup,
9 shader::ShaderRef,
10};
11
12const SHADER_ASSET_PATH: &str = "shaders/line_material.wgsl";
14
15fn main() {
16 App::new()
17 .add_plugins((DefaultPlugins, MaterialPlugin::<LineMaterial>::default()))
18 .add_systems(Startup, setup)
19 .run();
20}
21
22fn setup(
23 mut commands: Commands,
24 mut meshes: ResMut<Assets<Mesh>>,
25 mut materials: ResMut<Assets<LineMaterial>>,
26) {
27 commands.spawn((
29 Mesh3d(meshes.add(LineList {
30 lines: vec![
31 (Vec3::ZERO, Vec3::new(1.0, 1.0, 0.0)),
32 (Vec3::new(1.0, 1.0, 0.0), Vec3::new(1.0, 0.0, 0.0)),
33 ],
34 })),
35 MeshMaterial3d(materials.add(LineMaterial {
36 color: LinearRgba::GREEN,
37 })),
38 Transform::from_xyz(-1.5, 0.0, 0.0),
39 ));
40
41 commands.spawn((
43 Mesh3d(meshes.add(LineStrip {
44 points: vec![
45 Vec3::ZERO,
46 Vec3::new(1.0, 1.0, 0.0),
47 Vec3::new(2.0, 0.0, 0.0),
48 Vec3::new(2.0, 1.0, 0.0),
49 Vec3::new(3.0, 1.0, 0.0),
50 ],
51 indices: Indices::U16(vec![0, 1, u16::MAX , 2, 3, 4]),
52 })),
53 MeshMaterial3d(materials.add(LineMaterial {
54 color: LinearRgba::BLUE,
55 })),
56 Transform::from_xyz(0.5, 0.0, 0.0),
57 ));
58
59 commands.spawn((
61 Camera3d::default(),
62 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
63 ));
64}
65
66#[derive(Asset, TypePath, Default, AsBindGroup, Debug, Clone)]
67struct LineMaterial {
68 #[uniform(0)]
69 color: LinearRgba,
70}
71
72impl Material for LineMaterial {
73 fn fragment_shader() -> ShaderRef {
74 SHADER_ASSET_PATH.into()
75 }
76}
77
78#[derive(Debug, Clone)]
80struct LineList {
81 lines: Vec<(Vec3, Vec3)>,
82}
83
84impl From<LineList> for Mesh {
85 fn from(line: LineList) -> Self {
86 let vertices: Vec<_> = line.lines.into_iter().flat_map(|(a, b)| [a, b]).collect();
87
88 Mesh::new(
89 PrimitiveTopology::LineList,
92 RenderAssetUsages::RENDER_WORLD,
93 )
94 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
96 }
97}
98
99#[derive(Debug, Clone)]
101struct LineStrip {
102 points: Vec<Vec3>,
103 indices: Indices,
104}
105
106impl From<LineStrip> for Mesh {
107 fn from(line: LineStrip) -> Self {
108 Mesh::new(
109 PrimitiveTopology::LineStrip,
112 RenderAssetUsages::RENDER_WORLD,
113 )
114 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points)
116 .with_inserted_indices(line.indices)
117 }
118}