Submit a draw against a compiled material. Allocates (or reuses) a per-draw UBO slot, writes the MVP / model / tint / skin info, and queues the command for dispatch.
(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
joint_buffer: &wgpu::Buffer,
material: MaterialHandle,
mesh_handle: u64,
mesh_idx: usiz
| 1376 | /// a per-draw UBO slot, writes the MVP / model / tint / skin info, |
| 1377 | /// and queues the command for dispatch. |
| 1378 | pub fn submit_draw( |
| 1379 | &mut self, |
| 1380 | device: &wgpu::Device, |
| 1381 | queue: &wgpu::Queue, |
| 1382 | joint_buffer: &wgpu::Buffer, |
| 1383 | material: MaterialHandle, |
| 1384 | mesh_handle: u64, |
| 1385 | mesh_idx: usize, |
| 1386 | mvp: [[f32; 4]; 4], |
| 1387 | model: [[f32; 4]; 4], |
| 1388 | prev_mvp: [[f32; 4]; 4], |
| 1389 | tint: [f32; 4], |
| 1390 | skin_info: [u32; 4], |
| 1391 | ) { |
| 1392 | let idx = material as usize; |
| 1393 | if material == 0 || idx > self.pipelines.len() { return; } |
| 1394 | let bucket = match self.pipelines[idx - 1].as_ref() { |
| 1395 | Some(p) => p.bucket, |
| 1396 | None => return, |
| 1397 | }; |
| 1398 | |
| 1399 | let slot = self.next_draw_slot; |
| 1400 | self.next_draw_slot += 1; |
| 1401 | self.ensure_draw_slot(device, joint_buffer, slot); |
| 1402 | |
| 1403 | let per_draw = PerDrawUniforms { mvp, model, prev_mvp, model_tint: tint, skin_info }; |
| 1404 | queue.write_buffer(&self.per_draw_buffers[slot], 0, bytemuck::bytes_of(&per_draw)); |
| 1405 | |
| 1406 | let cmd = MaterialDrawCommand { |
| 1407 | material, mesh_handle, mesh_idx, draw_slot: slot, |
| 1408 | instance: None, |
| 1409 | }; |
| 1410 | if bucket.is_translucent() { |
| 1411 | self.translucent_commands.push(cmd); |
| 1412 | } else { |
| 1413 | self.commands.push(cmd); |
| 1414 | } |
| 1415 | } |
| 1416 | |
| 1417 | /// EN-001 — submit an instanced draw. Identical to `submit_draw` |
| 1418 | /// except the engine binds vertex slot 1 to the registered |