1use bytemuck::{Pod, Zeroable};
6
7pub trait Vertex: Pod {
12 fn layout() -> wgpu::VertexBufferLayout<'static>;
14}
15
16#[repr(C)]
20#[derive(Debug, Clone, Copy, Pod, Zeroable)]
21pub struct PositionColorVertex {
22 pub position: [f32; 3],
24 pub color: [f32; 3],
26}
27
28impl PositionColorVertex {
29 #[must_use]
31 pub const fn new(position: [f32; 3], color: [f32; 3]) -> Self {
32 Self { position, color }
33 }
34}
35
36impl Vertex for PositionColorVertex {
37 fn layout() -> wgpu::VertexBufferLayout<'static> {
38 const ATTRIBUTES: &[wgpu::VertexAttribute] = &[
39 wgpu::VertexAttribute {
41 format: wgpu::VertexFormat::Float32x3,
42 offset: 0,
43 shader_location: 0,
44 },
45 wgpu::VertexAttribute {
47 format: wgpu::VertexFormat::Float32x3,
48 offset: std::mem::size_of::<[f32; 3]>() as u64,
49 shader_location: 1,
50 },
51 ];
52
53 wgpu::VertexBufferLayout {
54 array_stride: std::mem::size_of::<PositionColorVertex>() as u64,
55 step_mode: wgpu::VertexStepMode::Vertex,
56 attributes: ATTRIBUTES,
57 }
58 }
59}
60
61#[repr(C)]
63#[derive(Debug, Clone, Copy, Pod, Zeroable)]
64pub struct PositionColorTexVertex {
65 pub position: [f32; 3],
67 pub color: [f32; 3],
69 pub tex_coords: [f32; 2],
71}
72
73impl PositionColorTexVertex {
74 #[must_use]
76 pub const fn new(position: [f32; 3], color: [f32; 3], tex_coords: [f32; 2]) -> Self {
77 Self {
78 position,
79 color,
80 tex_coords,
81 }
82 }
83}
84
85impl Vertex for PositionColorTexVertex {
86 fn layout() -> wgpu::VertexBufferLayout<'static> {
87 const ATTRIBUTES: &[wgpu::VertexAttribute] = &[
88 wgpu::VertexAttribute {
90 format: wgpu::VertexFormat::Float32x3,
91 offset: 0,
92 shader_location: 0,
93 },
94 wgpu::VertexAttribute {
96 format: wgpu::VertexFormat::Float32x3,
97 offset: std::mem::size_of::<[f32; 3]>() as u64,
98 shader_location: 1,
99 },
100 wgpu::VertexAttribute {
102 format: wgpu::VertexFormat::Float32x2,
103 offset: (std::mem::size_of::<[f32; 3]>() * 2) as u64,
104 shader_location: 2,
105 },
106 ];
107
108 wgpu::VertexBufferLayout {
109 array_stride: std::mem::size_of::<PositionColorTexVertex>() as u64,
110 step_mode: wgpu::VertexStepMode::Vertex,
111 attributes: ATTRIBUTES,
112 }
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_position_color_vertex_new() {
122 let vertex = PositionColorVertex::new([1.0, 2.0, 3.0], [0.5, 0.6, 0.7]);
123 assert_eq!(vertex.position, [1.0, 2.0, 3.0]);
124 assert_eq!(vertex.color, [0.5, 0.6, 0.7]);
125 }
126
127 #[test]
128 fn test_position_color_vertex_layout() {
129 let layout = PositionColorVertex::layout();
130 assert_eq!(
131 layout.array_stride,
132 std::mem::size_of::<PositionColorVertex>() as u64
133 );
134 assert_eq!(layout.step_mode, wgpu::VertexStepMode::Vertex);
135 assert_eq!(layout.attributes.len(), 2);
136
137 assert_eq!(layout.attributes[0].shader_location, 0);
139 assert_eq!(layout.attributes[0].format, wgpu::VertexFormat::Float32x3);
140 assert_eq!(layout.attributes[0].offset, 0);
141
142 assert_eq!(layout.attributes[1].shader_location, 1);
144 assert_eq!(layout.attributes[1].format, wgpu::VertexFormat::Float32x3);
145 assert_eq!(
146 layout.attributes[1].offset,
147 std::mem::size_of::<[f32; 3]>() as u64
148 );
149 }
150
151 #[test]
152 fn test_position_color_tex_vertex_new() {
153 let vertex = PositionColorTexVertex::new([1.0, 2.0, 3.0], [0.5, 0.6, 0.7], [0.0, 1.0]);
154 assert_eq!(vertex.position, [1.0, 2.0, 3.0]);
155 assert_eq!(vertex.color, [0.5, 0.6, 0.7]);
156 assert_eq!(vertex.tex_coords, [0.0, 1.0]);
157 }
158
159 #[test]
160 fn test_position_color_tex_vertex_layout() {
161 let layout = PositionColorTexVertex::layout();
162 assert_eq!(
163 layout.array_stride,
164 std::mem::size_of::<PositionColorTexVertex>() as u64
165 );
166 assert_eq!(layout.attributes.len(), 3);
167
168 assert_eq!(layout.attributes[2].shader_location, 2);
170 assert_eq!(layout.attributes[2].format, wgpu::VertexFormat::Float32x2);
171 }
172
173 #[test]
174 fn test_vertex_size_alignment() {
175 assert_eq!(std::mem::size_of::<PositionColorVertex>(), 24); assert_eq!(std::mem::size_of::<PositionColorTexVertex>(), 32); }
179
180 #[test]
181 fn test_vertex_is_pod() {
182 let vertex = PositionColorVertex::new([1.0, 0.0, 0.0], [1.0, 1.0, 1.0]);
184 let bytes: &[u8] = bytemuck::bytes_of(&vertex);
185 assert_eq!(bytes.len(), 24);
186 }
187}