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