Skip to main content

ferrum_wgpu/assets/
models.rs

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