1use std::ops::Range;
11
12use crate::{data_structures::texture::{self, create_default_sampler}, resources::pick::pick_layout};
13
14pub trait Vertex {
16 fn desc() -> wgpu::VertexBufferLayout<'static>;
17}
18
19#[repr(C)]
24#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable, PartialEq)]
25pub struct ModelVertex {
26 pub position: [f32; 3],
27 pub tex_coords: [f32; 2],
28 pub normal: [f32; 3],
29 pub tangent: [f32; 3],
31 pub bitangent: [f32; 3],
32}
33
34impl Vertex for ModelVertex {
35 fn desc() -> wgpu::VertexBufferLayout<'static> {
36 use std::mem;
37 wgpu::VertexBufferLayout {
38 array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
39 step_mode: wgpu::VertexStepMode::Vertex,
40 attributes: &[
41 wgpu::VertexAttribute {
42 offset: 0,
43 shader_location: 0,
45 format: wgpu::VertexFormat::Float32x3,
46 },
47 wgpu::VertexAttribute {
48 offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
49 shader_location: 1,
50 format: wgpu::VertexFormat::Float32x2,
51 },
52 wgpu::VertexAttribute {
53 offset: mem::size_of::<[f32; 5]>() as wgpu::BufferAddress,
54 shader_location: 2,
55 format: wgpu::VertexFormat::Float32x3,
56 },
57 wgpu::VertexAttribute {
58 offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
59 shader_location: 3,
60 format: wgpu::VertexFormat::Float32x3,
61 },
62 wgpu::VertexAttribute {
63 offset: mem::size_of::<[f32; 11]>() as wgpu::BufferAddress,
64 shader_location: 4,
65 format: wgpu::VertexFormat::Float32x3,
66 },
67 ],
68 }
69 }
70}
71
72#[derive(Clone, Debug)]
73pub struct Material {
74 pub name: String,
75 pub bind_group: wgpu::BindGroup,
76}
77
78impl Material {
79 pub fn new(
80 device: &wgpu::Device,
81 name: &str,
82 diffuse_texture: texture::Texture,
83 normal_texture: texture::Texture,
84 layout: &wgpu::BindGroupLayout,
85 ) -> Result<Self, anyhow::Error> {
86 let diffuse_texture_sampler = diffuse_texture
87 .sampler
88 .ok_or(anyhow::anyhow!("Diffuse texture missing sampler"))?;
89 let normal_texture_sampler = normal_texture
90 .sampler
91 .unwrap_or(create_default_sampler(device));
92 let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
93 layout,
94 entries: &[
95 wgpu::BindGroupEntry {
97 binding: 0,
98 resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
99 },
100 wgpu::BindGroupEntry {
101 binding: 1,
102 resource: wgpu::BindingResource::Sampler(&diffuse_texture_sampler),
103 },
104 wgpu::BindGroupEntry {
105 binding: 2,
106 resource: wgpu::BindingResource::TextureView(&normal_texture.view),
107 },
108 wgpu::BindGroupEntry {
109 binding: 3,
110 resource: wgpu::BindingResource::Sampler(&normal_texture_sampler),
111 },
112 ],
113 label: Some(name),
114 });
115 Ok(Self {
116 name: String::from(name),
117 bind_group,
118 })
119 }
120
121 pub fn new_pick_material(device: &wgpu::Device, name: &str, buffer: wgpu::Buffer) -> Self {
122 let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
123 layout: &pick_layout(device),
124 entries: &[
125 wgpu::BindGroupEntry {
127 binding: 0,
128 resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
129 buffer: &buffer,
130 offset: 0,
131 size: None,
132 }),
133 },
134 ],
135 label: Some(name),
136 });
137
138 Self {
139 name: String::from(name),
140 bind_group,
141 }
142 }
143}
144
145#[derive(Clone, Debug)]
146pub struct Mesh {
147 pub name: String,
148 pub vertex_buffer: wgpu::Buffer,
149 pub index_buffer: wgpu::Buffer,
150 pub num_elements: u32,
151 pub material: usize,
152}
153
154#[derive(Debug)]
155pub struct Model {
156 pub meshes: Vec<Mesh>,
157 pub materials: Vec<Material>,
158}
159
160pub trait DrawModel<'a> {
161 fn draw_mesh(
162 &mut self,
163 mesh: &'a Mesh,
164 material: &'a Material,
165 camera_bind_group: &'a wgpu::BindGroup,
166 light_bind_group: &'a wgpu::BindGroup,
167 );
168 fn draw_mesh_instanced(
169 &mut self,
170 mesh: &'a Mesh,
171 material: &'a Material,
172 instances: Range<u32>,
173 camera_bind_group: &'a wgpu::BindGroup,
174 light_bind_group: &'a wgpu::BindGroup,
175 );
176
177 fn draw_model(
178 &mut self,
179 model: &'a Model,
180 camera_bind_group: &'a wgpu::BindGroup,
181 light_bind_group: &'a wgpu::BindGroup,
182 );
183 fn draw_model_instanced(
184 &mut self,
185 model: &'a Model,
186 instances: Range<u32>,
187 camera_bind_group: &'a wgpu::BindGroup,
188 light_bind_group: &'a wgpu::BindGroup,
189 );
190}
191
192impl<'a, 'b> DrawModel<'b> for wgpu::RenderPass<'a>
193where
194 'a: 'b,
195{
196 fn draw_mesh(
197 &mut self,
198 mesh: &'b Mesh,
199 material: &'b Material,
200 camera_bind_group: &'b wgpu::BindGroup,
201 light_bind_group: &'b wgpu::BindGroup,
202 ) {
203 self.draw_mesh_instanced(mesh, material, 0..1, camera_bind_group, light_bind_group);
204 }
205
206 fn draw_mesh_instanced(
207 &mut self,
208 mesh: &'b Mesh,
209 material: &'b Material,
210 instances: Range<u32>,
211 camera_bind_group: &'b wgpu::BindGroup,
212 light_bind_group: &'b wgpu::BindGroup,
213 ) {
214 self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
215 self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
216 self.set_bind_group(0, &material.bind_group, &[]);
217 self.set_bind_group(1, camera_bind_group, &[]);
218 self.set_bind_group(2, light_bind_group, &[]);
219 self.draw_indexed(0..mesh.num_elements, 0, instances);
220 }
221
222 fn draw_model(
223 &mut self,
224 model: &'b Model,
225 camera_bind_group: &'b wgpu::BindGroup,
226 light_bind_group: &'b wgpu::BindGroup,
227 ) {
228 self.draw_model_instanced(model, 0..1, camera_bind_group, light_bind_group);
229 }
230
231 fn draw_model_instanced(
232 &mut self,
233 model: &'b Model,
234 instances: Range<u32>,
235 camera_bind_group: &'b wgpu::BindGroup,
236 light_bind_group: &'b wgpu::BindGroup,
237 ) {
238 for mesh in &model.meshes {
239 let material = &model.materials[mesh.material];
240 self.draw_mesh_instanced(
241 mesh,
242 material,
243 instances.clone(),
244 camera_bind_group,
245 light_bind_group,
246 );
247 }
248 }
249}
250
251pub trait DrawLight<'a> {
252 #[allow(dead_code)]
253 fn draw_light_mesh(
254 &mut self,
255 mesh: &'a Mesh,
256 camera_bind_group: &'a wgpu::BindGroup,
257 light_bind_group: &'a wgpu::BindGroup,
258 );
259 fn draw_light_mesh_instanced(
260 &mut self,
261 mesh: &'a Mesh,
262 instances: Range<u32>,
263 camera_bind_group: &'a wgpu::BindGroup,
264 light_bind_group: &'a wgpu::BindGroup,
265 );
266
267 fn draw_light_model(
268 &mut self,
269 model: &'a Model,
270 camera_bind_group: &'a wgpu::BindGroup,
271 light_bind_group: &'a wgpu::BindGroup,
272 );
273 fn draw_light_model_instanced(
274 &mut self,
275 model: &'a Model,
276 instances: Range<u32>,
277 camera_bind_group: &'a wgpu::BindGroup,
278 light_bind_group: &'a wgpu::BindGroup,
279 );
280}
281
282impl<'a, 'b> DrawLight<'b> for wgpu::RenderPass<'a>
283where
284 'b: 'a,
285{
286 fn draw_light_mesh(
287 &mut self,
288 mesh: &'b Mesh,
289 camera_bind_group: &'b wgpu::BindGroup,
290 light_bind_group: &'b wgpu::BindGroup,
291 ) {
292 self.draw_light_mesh_instanced(mesh, 0..1, camera_bind_group, light_bind_group);
293 }
294
295 fn draw_light_mesh_instanced(
296 &mut self,
297 mesh: &'b Mesh,
298 instances: Range<u32>,
299 camera_bind_group: &'b wgpu::BindGroup,
300 light_bind_group: &'b wgpu::BindGroup,
301 ) {
302 self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
303 self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
304 self.set_bind_group(0, camera_bind_group, &[]);
305 self.set_bind_group(1, light_bind_group, &[]);
306 self.draw_indexed(0..mesh.num_elements, 0, instances);
307 }
308
309 fn draw_light_model(
310 &mut self,
311 model: &'b Model,
312 camera_bind_group: &'b wgpu::BindGroup,
313 light_bind_group: &'b wgpu::BindGroup,
314 ) {
315 self.draw_light_model_instanced(model, 0..1, camera_bind_group, light_bind_group);
316 }
317 fn draw_light_model_instanced(
318 &mut self,
319 model: &'b Model,
320 instances: Range<u32>,
321 camera_bind_group: &'b wgpu::BindGroup,
322 light_bind_group: &'b wgpu::BindGroup,
323 ) {
324 for mesh in &model.meshes {
325 self.draw_light_mesh_instanced(
326 mesh,
327 instances.clone(),
328 camera_bind_group,
329 light_bind_group,
330 );
331 }
332 }
333}