Don't force loaded model indicies to U32

This commit is contained in:
SeanOMik 2023-10-08 00:03:53 -04:00
parent 8f7288339d
commit 02a0eea7b3
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
4 changed files with 58 additions and 31 deletions

View File

@ -2,7 +2,7 @@ use std::sync::Arc;
use base64::Engine; use base64::Engine;
use crate::{ResourceLoader, LoaderError, Mesh, Model, MeshVertexAttribute, VertexAttributeData, Resource, Material, ResHandle}; use crate::{ResourceLoader, LoaderError, Mesh, Model, MeshVertexAttribute, VertexAttributeData, Resource, Material, MeshIndices};
use tracing::debug; use tracing::debug;
@ -67,10 +67,11 @@ impl ModelLoader {
// read the indices // read the indices
if let Some(indices) = reader.read_indices() { if let Some(indices) = reader.read_indices() {
let indices: Vec<u32> = match indices { let indices: MeshIndices = match indices {
gltf::mesh::util::ReadIndices::U8(i) => i.map(|i| i as u32).collect(), // wpgu doesn't support u8 indices, so those must be converted to u16
gltf::mesh::util::ReadIndices::U16(i) => i.map(|i| i as u32).collect(), gltf::mesh::util::ReadIndices::U8(i) => MeshIndices::U16(i.map(|i| i as u16).collect()),
gltf::mesh::util::ReadIndices::U32(i) => i.collect(), gltf::mesh::util::ReadIndices::U16(i) => MeshIndices::U16(i.collect()),
gltf::mesh::util::ReadIndices::U32(i) => MeshIndices::U32(i.collect()),
}; };
new_mesh.indices = Some(indices); new_mesh.indices = Some(indices);

View File

@ -1,6 +1,32 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{Material, ResHandle}; use crate::Material;
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub enum MeshIndices {
//U8(Vec<u8>),
U16(Vec<u16>),
U32(Vec<u32>),
}
/* impl From<Vec<u8>> for MeshIndices {
fn from(value: Vec<u8>) -> Self {
MeshIndices::U8(value)
}
} */
impl From<Vec<u16>> for MeshIndices {
fn from(value: Vec<u16>) -> Self {
MeshIndices::U16(value)
}
}
impl From<Vec<u32>> for MeshIndices {
fn from(value: Vec<u32>) -> Self {
MeshIndices::U32(value)
}
}
#[repr(C)] #[repr(C)]
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -45,7 +71,7 @@ pub enum MeshVertexAttribute {
#[derive(Clone, Default, edict::Component)] #[derive(Clone, Default, edict::Component)]
pub struct Mesh { pub struct Mesh {
pub attributes: HashMap<MeshVertexAttribute, VertexAttributeData>, pub attributes: HashMap<MeshVertexAttribute, VertexAttributeData>,
pub indices: Option<Vec<u32>>, pub indices: Option<MeshIndices>,
material: Option<Material>, material: Option<Material>,
} }

View File

@ -1,8 +1,8 @@
use std::{ops::Range, cell::Ref}; use std::ops::Range;
use wgpu::{PipelineLayout, RenderPipeline, RenderPass, VertexBufferLayout, BindGroupLayout}; use wgpu::{PipelineLayout, RenderPipeline, RenderPass, VertexBufferLayout, BindGroupLayout};
use super::{render_job::RenderJob, vertex::Vertex, desc_buf_lay::DescVertexBufferLayout, texture::RenderTexture}; use super::{render_job::RenderJob, texture::RenderTexture};
pub struct FullRenderPipeline { pub struct FullRenderPipeline {
layout: PipelineLayout, layout: PipelineLayout,

View File

@ -36,7 +36,7 @@ pub trait Renderer {
struct RenderBufferStorage { struct RenderBufferStorage {
buffer_vertex: BufferStorage, buffer_vertex: BufferStorage,
buffer_indices: Option<BufferStorage>, buffer_indices: Option<(wgpu::IndexFormat, BufferStorage)>,
render_texture: Option<RenderTexture>, render_texture: Option<RenderTexture>,
texture_bindgroup: Option<BindGroup>, texture_bindgroup: Option<BindGroup>,
@ -404,14 +404,6 @@ impl BasicRenderer {
s s
} }
fn find_next_multiple(n: u32, mul: u32) -> u32 {
if n % mul == 0 {
n
} else {
n + (mul - n % mul)
}
}
fn update_mesh_buffers(&mut self, entity: EntityId, mesh: &Mesh) { fn update_mesh_buffers(&mut self, entity: EntityId, mesh: &Mesh) {
if let Some(buffers) = self.buffer_storage.get_mut(&entity) { if let Some(buffers) = self.buffer_storage.get_mut(&entity) {
// check if the buffer sizes dont match. If they dont, completely remake the buffers // check if the buffer sizes dont match. If they dont, completely remake the buffers
@ -438,16 +430,19 @@ impl BasicRenderer {
// update the indices if they're given // update the indices if they're given
if let Some(index_buffer) = buffers.buffer_indices.as_ref() { if let Some(index_buffer) = buffers.buffer_indices.as_ref() {
let index_buffer = index_buffer.buffer(); let aligned_indices = match mesh.indices.as_ref().unwrap() {
let indices = mesh.indices.as_ref().unwrap().as_slice(); // U16 indices need to be aligned to u32, for wpgu, which are 4-bytes in size.
let (_, indices, _) = bytemuck::pod_align_to::<u32, u32>(indices); // TODO: Don't force indicies into u32 lyra_resource::MeshIndices::U16(v) => bytemuck::pod_align_to::<u16, u32>(v).1,
lyra_resource::MeshIndices::U32(v) => bytemuck::pod_align_to::<u32, u32>(v).1,
self.queue.write_buffer(index_buffer, 0, bytemuck::cast_slice(&indices)); };
let index_buffer = index_buffer.1.buffer();
self.queue.write_buffer(index_buffer, 0, bytemuck::cast_slice(&aligned_indices));
} }
} }
} }
fn create_vertex_index_buffers(&mut self, mesh: &Mesh) -> (BufferStorage, Option<BufferStorage>) { fn create_vertex_index_buffers(&mut self, mesh: &Mesh) -> (BufferStorage, Option<(wgpu::IndexFormat, BufferStorage)>) {
let vertices = mesh.position().unwrap(); let vertices = mesh.position().unwrap();
let vertex_buffer = self.device.create_buffer_init( let vertex_buffer = self.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor { &wgpu::util::BufferInitDescriptor {
@ -458,26 +453,31 @@ impl BasicRenderer {
); );
let vertex_buffer = BufferStorage::new(vertex_buffer, 0, vertices.len()); let vertex_buffer = BufferStorage::new(vertex_buffer, 0, vertices.len());
let buffer_indices = match mesh.indices.as_ref() { let indices = match mesh.indices.as_ref() {
Some(indices) => { Some(indices) => {
let (idx_type, len, contents) = match indices {
lyra_resource::MeshIndices::U16(v) => (wgpu::IndexFormat::Uint16, v.len(), bytemuck::cast_slice(&v)),
lyra_resource::MeshIndices::U32(v) => (wgpu::IndexFormat::Uint32, v.len(), bytemuck::cast_slice(&v)),
};
let index_buffer = self.device.create_buffer_init( let index_buffer = self.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor { &wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"), label: Some("Index Buffer"),
contents: bytemuck::cast_slice(&indices), contents,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages:: COPY_DST, usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages:: COPY_DST,
} }
); );
let buffer_indices = BufferStorage::new(index_buffer, 0, indices.len()); let buffer_indices = BufferStorage::new(index_buffer, 0, len);
Some(buffer_indices) Some((idx_type, buffer_indices))
}, },
None => { None => {
None None
} }
}; };
( vertex_buffer, buffer_indices ) ( vertex_buffer, indices )
} }
fn create_mesh_buffers(&mut self, mesh: &Mesh, transform_indices: TransformBufferIndices) -> RenderBufferStorage { fn create_mesh_buffers(&mut self, mesh: &Mesh, transform_indices: TransformBufferIndices) -> RenderBufferStorage {
@ -676,11 +676,11 @@ impl Renderer for BasicRenderer {
render_pass.set_bind_group(2, &self.camera_bind_group, &[]); render_pass.set_bind_group(2, &self.camera_bind_group, &[]);
// if this mesh uses indices, use them to draw the mesh // if this mesh uses indices, use them to draw the mesh
if let Some(indices) = buffers.buffer_indices.as_ref() { if let Some((idx_type, indices)) = buffers.buffer_indices.as_ref() {
let indices_len = indices.count() as u32; let indices_len = indices.count() as u32;
render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..)); render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..));
render_pass.set_index_buffer(indices.buffer().slice(..), wgpu::IndexFormat::Uint32); render_pass.set_index_buffer(indices.buffer().slice(..), idx_type.clone());
render_pass.draw_indexed(0..indices_len, 0, 0..1); render_pass.draw_indexed(0..indices_len, 0, 0..1);
} else { } else {
let vertices = mesh.position().unwrap(); let vertices = mesh.position().unwrap();