1use crate::{
2 app::App,
3 assets::{plugin::AssetPlugin, upload::Asset},
4 ecs::plugin::Plugin,
5 wgpu::backend::WGPUBackend,
6};
7
8#[repr(C)]
9#[derive(Copy, Clone, Default, bytemuck::Pod, bytemuck::Zeroable)]
10pub struct Vertex {
11 pub position: glam::Vec3,
12 pub tex_coords: glam::Vec2,
13 pub normal: glam::Vec3,
14 pub tangent: glam::Vec4,
15}
16
17impl Vertex {
18 pub fn new(
19 position: glam::Vec3,
20 tex_coords: glam::Vec2,
21 normal: glam::Vec3,
22 tangent: glam::Vec4,
23 ) -> Self {
24 Self {
25 position,
26 tex_coords,
27 normal,
28 tangent,
29 }
30 }
31
32 pub fn layout() -> wgpu::VertexBufferLayout<'static> {
33 const ATTRS: &[wgpu::VertexAttribute] = &wgpu::vertex_attr_array![
34 0 => Float32x3, 1 => Float32x2, 2 => Float32x3, 3 => Float32x4, ];
39 wgpu::VertexBufferLayout {
40 array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
41 step_mode: wgpu::VertexStepMode::Vertex,
42 attributes: ATTRS,
43 }
44 }
45}
46
47#[repr(C)]
50#[derive(Copy, Clone, Default, bytemuck::Pod, bytemuck::Zeroable)]
51pub struct InstanceVertex {
52 pub model: glam::Mat4,
53}
54
55impl InstanceVertex {
56 pub fn new(model: glam::Mat4) -> Self {
57 Self { model }
58 }
59
60 pub fn layout() -> wgpu::VertexBufferLayout<'static> {
61 const ATTRS: &[wgpu::VertexAttribute] = &wgpu::vertex_attr_array![
62 4 => Float32x4, 5 => Float32x4, 6 => Float32x4, 7 => Float32x4, ];
67 wgpu::VertexBufferLayout {
68 array_stride: std::mem::size_of::<InstanceVertex>() as wgpu::BufferAddress,
69 step_mode: wgpu::VertexStepMode::Instance,
70 attributes: ATTRS,
71 }
72 }
73}
74
75pub struct MeshDescriptor {
76 pub vertices: Vec<Vertex>,
77 pub indices: Vec<u32>,
78}
79
80pub struct GPUMesh {
81 pub vertex_buffer: wgpu::Buffer,
82 pub index_buffer: wgpu::Buffer,
83 pub index_count: u32,
84}
85
86impl Asset<WGPUBackend> for GPUMesh {
87 type Source = MeshDescriptor;
88 type Deps<'a> = ();
89
90 fn upload<'a>(source: &MeshDescriptor, backend: &WGPUBackend, _deps: &()) -> Option<Self> {
91 use wgpu::util::DeviceExt;
92 let vertex_buffer = backend
93 .device
94 .create_buffer_init(&wgpu::util::BufferInitDescriptor {
95 label: Some("Mesh Vertex Buffer"),
96 contents: bytemuck::cast_slice(source.vertices.as_slice()),
97 usage: wgpu::BufferUsages::VERTEX,
98 });
99 let index_buffer = backend
100 .device
101 .create_buffer_init(&wgpu::util::BufferInitDescriptor {
102 label: Some("Mesh Index Buffer"),
103 contents: bytemuck::cast_slice(&source.indices),
104 usage: wgpu::BufferUsages::INDEX,
105 });
106 Some(Self {
107 vertex_buffer,
108 index_buffer,
109 index_count: source.indices.len() as u32,
110 })
111 }
112}
113
114#[derive(Default)]
115pub struct MeshPlugin;
116impl MeshPlugin {
117 pub fn new() -> Self {
118 Self
119 }
120}
121impl Plugin for MeshPlugin {
122 fn build(&self, app: &mut App) {
123 app.add_plugin(AssetPlugin::<WGPUBackend, GPUMesh>::new());
124 }
125}