Skip to main content

ferrum_wgpu/assets/
models.rs

1use cgmath::{Matrix3, Matrix4, One, Quaternion, Vector3, Zero};
2
3use crate::renderer;
4
5pub trait Vertex {
6    fn desc() -> wgpu::VertexBufferLayout<'static>;
7}
8
9#[repr(C)]
10#[derive(Debug, Clone, Copy, bytemuck::Zeroable, bytemuck::Pod)]
11pub struct ModelVertex {
12    pub position: [f32; 3],
13    pub text_cords: [f32; 2],
14    pub normal: [f32; 3],
15    pub color: [f32; 3],
16    pub tangent: [f32; 3],
17    pub bitangent: [f32; 3],
18}
19
20impl Vertex for ModelVertex {
21    fn desc() -> wgpu::VertexBufferLayout<'static> {
22        use std::mem;
23        wgpu::VertexBufferLayout {
24            array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
25            step_mode: wgpu::VertexStepMode::Vertex,
26            attributes: &[
27                wgpu::VertexAttribute {
28                    offset: 0,
29                    shader_location: 0,
30                    format: wgpu::VertexFormat::Float32x3,
31                },
32                wgpu::VertexAttribute {
33                    offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
34                    shader_location: 1,
35                    format: wgpu::VertexFormat::Float32x2,
36                },
37                wgpu::VertexAttribute {
38                    offset: mem::size_of::<[f32; 5]>() as wgpu::BufferAddress,
39                    shader_location: 2,
40                    format: wgpu::VertexFormat::Float32x3,
41                },
42                wgpu::VertexAttribute {
43                    offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
44                    shader_location: 3,
45                    format: wgpu::VertexFormat::Float32x3,
46                },
47                wgpu::VertexAttribute {
48                    offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
49                    shader_location: 4,
50                    format: wgpu::VertexFormat::Float32x3,
51                },
52                wgpu::VertexAttribute {
53                    offset: mem::size_of::<[f32; 11]>() as wgpu::BufferAddress,
54                    shader_location: 5,
55                    format: wgpu::VertexFormat::Float32x3,
56                },
57            ],
58        }
59    }
60}
61
62pub trait DrawModel<'a> {
63    fn draw_mesh(
64        &mut self,
65        mesh: &'a renderer::Mesh,
66        material: &'a renderer::Material,
67        instances: std::ops::Range<u32>,
68        instance_buffer: &'a wgpu::Buffer,
69        camera_bind_group: &'a wgpu::BindGroup,
70        light_bind_group: &'a wgpu::BindGroup,
71        shadow_bind_group: &'a wgpu::BindGroup,
72        wind_bind_group: &'a wgpu::BindGroup,
73    );
74
75    fn draw_model(
76        &mut self,
77        model: &'a Model,
78        camera_bind_group: &'a wgpu::BindGroup,
79        light_bind_group: &'a wgpu::BindGroup,
80        shadow_bind_group: &'a wgpu::BindGroup,
81        wind_bind_group: &'a wgpu::BindGroup,
82    );
83}
84
85impl<'a, 'b> DrawModel<'b> for wgpu::RenderPass<'a>
86where
87    'b: 'a,
88{
89    fn draw_mesh(
90        &mut self,
91        mesh: &'b renderer::Mesh,
92        material: &'b renderer::Material,
93        instances: std::ops::Range<u32>,
94        instance_buffer: &'a wgpu::Buffer,
95        camera_bind_group: &'b wgpu::BindGroup,
96        light_bind_group: &'a wgpu::BindGroup,
97        shadow_bind_group: &'a wgpu::BindGroup,
98        wind_bind_group: &'a wgpu::BindGroup,
99    ) {
100        self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
101        self.set_vertex_buffer(1, instance_buffer.slice(..));
102        self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
103        self.set_bind_group(0, &material.bind_group, &[]);
104        self.set_bind_group(1, camera_bind_group, &[]);
105        self.set_bind_group(2, light_bind_group, &[]);
106        self.set_bind_group(3, shadow_bind_group, &[]);
107        self.set_bind_group(4, wind_bind_group, &[]);
108        self.draw_indexed(0..mesh.indices, 0, instances);
109    }
110
111    fn draw_model(
112        &mut self,
113        model: &'b Model,
114        camera_bind_group: &'b wgpu::BindGroup,
115        light_bind_group: &'a wgpu::BindGroup,
116        shadow_bind_group: &'a wgpu::BindGroup,
117        wind_bind_group: &'a wgpu::BindGroup,
118    ) {
119        for mesh in &model.meshes {
120            let material: &renderer::Material = &model.materials[mesh.material];
121            self.draw_mesh(
122                mesh,
123                material,
124                0..model.instances.len() as u32,
125                &model.instance_buffer,
126                camera_bind_group,
127                light_bind_group,
128                shadow_bind_group,
129                wind_bind_group,
130            );
131        }
132    }
133}
134
135#[repr(C)]
136#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]
137#[allow(dead_code)]
138pub struct InstanceRaw {
139    pub model: [[f32; 4]; 4],
140    pub normals: [[f32; 3]; 3],
141    pub wind_weight: f32,
142}
143
144impl InstanceRaw {
145    pub fn desc() -> wgpu::VertexBufferLayout<'static> {
146        use std::mem;
147
148        wgpu::VertexBufferLayout {
149            array_stride: mem::size_of::<InstanceRaw>() as wgpu::BufferAddress,
150            step_mode: wgpu::VertexStepMode::Instance,
151            attributes: &[
152                wgpu::VertexAttribute {
153                    format: wgpu::VertexFormat::Float32x4,
154                    offset: 0,
155                    shader_location: 6,
156                },
157                wgpu::VertexAttribute {
158                    format: wgpu::VertexFormat::Float32x4,
159                    offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress,
160                    shader_location: 7,
161                },
162                wgpu::VertexAttribute {
163                    format: wgpu::VertexFormat::Float32x4,
164                    offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
165                    shader_location: 8,
166                },
167                wgpu::VertexAttribute {
168                    format: wgpu::VertexFormat::Float32x4,
169                    offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
170                    shader_location: 9,
171                },
172                wgpu::VertexAttribute {
173                    format: wgpu::VertexFormat::Float32x3,
174                    offset: mem::size_of::<[f32; 16]>() as wgpu::BufferAddress,
175                    shader_location: 10,
176                },
177                wgpu::VertexAttribute {
178                    format: wgpu::VertexFormat::Float32x3,
179                    offset: mem::size_of::<[f32; 19]>() as wgpu::BufferAddress,
180                    shader_location: 11,
181                },
182                wgpu::VertexAttribute {
183                    format: wgpu::VertexFormat::Float32x3,
184                    offset: mem::size_of::<[f32; 22]>() as wgpu::BufferAddress,
185                    shader_location: 12,
186                },
187                wgpu::VertexAttribute {
188                    format: wgpu::VertexFormat::Float32,
189                    offset: mem::size_of::<[f32; 25]>() as wgpu::BufferAddress,
190                    shader_location: 13,
191                },
192            ],
193        }
194    }
195}
196
197pub struct Instance {
198    pub position: cgmath::Vector3<f32>,
199    pub rotation: cgmath::Quaternion<f32>,
200    pub scale: cgmath::Vector3<f32>,
201    pub wind_weight: f32,
202}
203
204impl Instance {
205    pub fn new(
206        position: cgmath::Vector3<f32>,
207        rotation: cgmath::Quaternion<f32>,
208        scale: cgmath::Vector3<f32>,
209    ) -> Self {
210        Self {
211            position,
212            rotation,
213            scale,
214            wind_weight: 0.0,
215        }
216    }
217
218    pub fn with_wind(mut self, weight: f32) -> Self {
219        self.wind_weight = weight;
220        self
221    }
222
223    pub fn to_raw(&self) -> InstanceRaw {
224        let translation: Matrix4<f32> = cgmath::Matrix4::from_translation(self.position);
225        let rotation: Matrix4<f32> = cgmath::Matrix4::from(self.rotation);
226        let scale: Matrix4<f32> =
227            cgmath::Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, self.scale.z);
228
229        let normals: Matrix3<f32> = cgmath::Matrix3::from(self.rotation);
230
231        InstanceRaw {
232            model: (translation * rotation * scale).into(),
233            normals: normals.into(),
234            wind_weight: self.wind_weight,
235        }
236    }
237}
238
239impl Default for Instance {
240    fn default() -> Self {
241        Self {
242            position: Vector3::zero(),
243            rotation: Quaternion::one(),
244            scale: Vector3::new(1.0, 1.0, 1.0),
245            wind_weight: 0.0,
246        }
247    }
248}
249
250pub trait DrawLight<'a> {
251    fn draw_light_model(
252        &mut self,
253        model: &'a Model,
254        camera_bind_group: &'a wgpu::BindGroup,
255        light_bind_group: &'a wgpu::BindGroup,
256    );
257}
258
259impl<'a, 'b> DrawLight<'b> for wgpu::RenderPass<'a>
260where
261    'b: 'a,
262{
263    fn draw_light_model(
264        &mut self,
265        model: &'a Model,
266        camera_bind_group: &'b wgpu::BindGroup,
267        light_bind_group: &'b wgpu::BindGroup,
268    ) {
269        for mesh in &model.meshes {
270            let material: &renderer::Material = &model.materials[mesh.material];
271            self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
272            self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
273            self.set_bind_group(0, camera_bind_group, &[]);
274            self.set_bind_group(1, light_bind_group, &[]);
275            self.set_bind_group(2, &material.bind_group, &[]);
276            self.draw_indexed(0..mesh.indices, 0, 0..1);
277        }
278    }
279}
280
281pub trait DrawShadow<'a> {
282    fn draw_shadow_model(&mut self, model: &'a Model, light_bind_group: &'a wgpu::BindGroup);
283}
284
285impl<'a, 'b> DrawShadow<'b> for wgpu::RenderPass<'a>
286where
287    'b: 'a,
288{
289    fn draw_shadow_model(&mut self, model: &'a Model, light_bind_group: &'b wgpu::BindGroup) {
290        for mesh in &model.meshes {
291            self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
292            self.set_vertex_buffer(1, model.instance_buffer.slice(..));
293            self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
294            self.set_bind_group(0, light_bind_group, &[]);
295            self.draw_indexed(0..mesh.indices, 0, 0..model.instances.len() as u32);
296        }
297    }
298}
299
300pub struct Model {
301    pub meshes: Vec<renderer::Mesh>,
302    pub materials: Vec<renderer::Material>,
303    pub instances: Vec<Instance>,
304    pub instance_buffer: wgpu::Buffer,
305    pub type_model: TypeModel,
306}
307
308pub struct ModelDesc<'a> {
309    pub path: &'a str,
310    pub instances: Vec<Instance>,
311    pub kind: TypeModel,
312}
313
314impl<'a> ModelDesc<'a> {
315    pub fn new(path: &'a str, instances: Vec<Instance>, kind: TypeModel) -> Self {
316        Self {
317            path,
318            instances,
319            kind,
320        }
321    }
322}
323
324#[derive(Clone)]
325pub enum TypeModel {
326    StaticObj,
327    PointOfLight,
328}