Decouple model handles from Renderer

This commit is contained in:
marceline-cramer 2022-02-15 17:13:24 -07:00
parent 7329e39970
commit 36fa7a9dea
2 changed files with 46 additions and 32 deletions

View File

@ -4,6 +4,12 @@ use crate::pool::{MaterialData, TextureData};
use crate::renderer::Renderer; use crate::renderer::Renderer;
use crate::scene::MeshInstance; use crate::scene::MeshInstance;
pub trait OnLoad {
fn load_mesh(&mut self, mesh_data: &MeshData) -> MeshHandle;
fn load_texture(&mut self, texture_data: &TextureData) -> TextureHandle;
fn load_material(&mut self, material_data: &MaterialData) -> MaterialHandle;
}
pub struct BasicMesh { pub struct BasicMesh {
pub mesh_handle: MeshHandle, pub mesh_handle: MeshHandle,
pub material_handle: MaterialHandle, pub material_handle: MaterialHandle,
@ -24,7 +30,7 @@ pub struct ObjModel {
} }
impl ObjModel { impl ObjModel {
pub fn load(ren: &mut Renderer) -> Self { pub fn load(mut on_load: impl OnLoad) -> Self {
use tobj::*; use tobj::*;
let model_data = include_bytes!("assets/viking_room/model.obj").to_vec(); let model_data = include_bytes!("assets/viking_room/model.obj").to_vec();
@ -64,7 +70,7 @@ impl ObjModel {
indices.extend(m.mesh.indices.iter().map(|i| i + index_base)); indices.extend(m.mesh.indices.iter().map(|i| i + index_base));
let mesh_data = MeshData { vertices, indices }; let mesh_data = MeshData { vertices, indices };
let mesh_handle = ren.mesh_pool.allocate(&ren.device, &mesh_data); let mesh_handle = on_load.load_mesh(&mesh_data);
let albedo_data = include_bytes!("assets/viking_room/albedo.png"); let albedo_data = include_bytes!("assets/viking_room/albedo.png");
let albedo = image::load_from_memory(albedo_data).unwrap(); let albedo = image::load_from_memory(albedo_data).unwrap();
@ -85,14 +91,10 @@ impl ObjModel {
data: albedo_rgba, data: albedo_rgba,
}; };
let albedo = ren let albedo = on_load.load_texture(&albedo_data);
.texture_pool
.allocate(&ren.device, &ren.queue, &albedo_data);
let material_data = MaterialData { albedo }; let material_data = MaterialData { albedo };
let material_handle = let material_handle = on_load.load_material(&material_data);
ren.material_pool
.allocate(&ren.device, &ren.texture_pool, &material_data);
let mesh = BasicMesh { let mesh = BasicMesh {
mesh_handle, mesh_handle,
@ -111,12 +113,12 @@ pub struct GltfModel {
} }
impl GltfModel { impl GltfModel {
pub fn load(ren: &mut Renderer) -> Self { pub fn load(on_load: impl OnLoad) -> Self {
use gltf::*; use gltf::*;
let model_data = include_bytes!("assets/DamagedHelmet.glb"); let model_data = include_bytes!("assets/DamagedHelmet.glb");
let model = Gltf::from_slice(model_data.as_slice()).unwrap(); let model = Gltf::from_slice(model_data.as_slice()).unwrap();
let loader = GltfLoader::load(&model, ren); let loader = GltfLoader::load(&model, on_load);
Self { Self {
meshes: loader.meshes, meshes: loader.meshes,
@ -130,21 +132,21 @@ impl GltfModel {
} }
} }
pub struct GltfLoader<'a> { pub struct GltfLoader<'a, T: OnLoad> {
pub model: &'a gltf::Gltf, pub model: &'a gltf::Gltf,
pub buffers: Vec<Vec<u8>>, pub buffers: Vec<Vec<u8>>,
pub ren: &'a mut Renderer, pub on_load: T,
pub meshes: Vec<BasicMesh>, pub meshes: Vec<BasicMesh>,
} }
impl<'a> GltfLoader<'a> { impl<'a, T: OnLoad> GltfLoader<'a, T> {
pub fn load(model: &'a gltf::Gltf, ren: &'a mut Renderer) -> Self { pub fn load(model: &'a gltf::Gltf, on_load: T) -> Self {
let buffers = Self::load_buffers(model); let buffers = Self::load_buffers(model);
let mut loader = Self { let mut loader = Self {
model, model,
buffers, buffers,
ren, on_load,
meshes: Default::default(), meshes: Default::default(),
}; };
@ -199,11 +201,7 @@ impl<'a> GltfLoader<'a> {
let base_color = pbr.base_color_texture().unwrap().texture(); let base_color = pbr.base_color_texture().unwrap().texture();
let albedo = self.load_texture(base_color); let albedo = self.load_texture(base_color);
let material_data = MaterialData { albedo }; self.on_load.load_material(&MaterialData { albedo })
self.ren
.material_pool
.allocate(&self.ren.device, &self.ren.texture_pool, &material_data)
} }
pub fn load_texture(&mut self, texture: gltf::Texture) -> TextureHandle { pub fn load_texture(&mut self, texture: gltf::Texture) -> TextureHandle {
@ -234,15 +232,11 @@ impl<'a> GltfLoader<'a> {
rgba rgba
}; };
let data = TextureData { self.on_load.load_texture(&TextureData {
width: dimensions.0, width: dimensions.0,
height: dimensions.1, height: dimensions.1,
data: rgba, data: rgba,
}; })
self.ren
.texture_pool
.allocate(&self.ren.device, &self.ren.queue, &data)
} }
pub fn load_primitive_mesh(&mut self, primitive: gltf::Primitive) -> MeshHandle { pub fn load_primitive_mesh(&mut self, primitive: gltf::Primitive) -> MeshHandle {
@ -281,8 +275,7 @@ impl<'a> GltfLoader<'a> {
ReadIndices::U8(indices) => indices.map(|i| i as u32).collect(), ReadIndices::U8(indices) => indices.map(|i| i as u32).collect(),
}; };
let mesh_data = MeshData { vertices, indices }; self.on_load.load_mesh(&MeshData { vertices, indices })
self.ren.mesh_pool.allocate(&self.ren.device, &mesh_data)
} }
} }

View File

@ -1,8 +1,10 @@
use super::camera::Camera; use super::camera::Camera;
use super::commands::{Command, CommandSet}; use super::commands::{Command, CommandSet};
use super::mesh::Vertex; use super::mesh::{MeshData, Vertex};
use super::pool::{MaterialPool, MeshGroup, MeshPool, TexturePool}; use super::pool::*;
use super::scene::{Scene, PointLight}; use super::scene::{PointLight, Scene};
use crate::handle::*;
use crate::model::OnLoad;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
pub struct Renderer { pub struct Renderer {
@ -255,7 +257,10 @@ impl Renderer {
bytemuck::cast_slice(&[self.camera_uniform]), bytemuck::cast_slice(&[self.camera_uniform]),
); );
let Scene { meshes, point_lights } = scene; let Scene {
meshes,
point_lights,
} = scene;
let mesh_commands = CommandSet::build(meshes); let mesh_commands = CommandSet::build(meshes);
// TODO persistent staging buffer (write_buffer creates a new one per call) // TODO persistent staging buffer (write_buffer creates a new one per call)
@ -349,6 +354,22 @@ impl Renderer {
} }
} }
impl OnLoad for &mut Renderer {
fn load_mesh(&mut self, mesh_data: &MeshData) -> MeshHandle {
self.mesh_pool.allocate(&self.device, mesh_data)
}
fn load_texture(&mut self, texture_data: &TextureData) -> TextureHandle {
self.texture_pool
.allocate(&self.device, &self.queue, texture_data)
}
fn load_material(&mut self, material_data: &MaterialData) -> MaterialHandle {
self.material_pool
.allocate(&self.device, &self.texture_pool, material_data)
}
}
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct CameraUniform { struct CameraUniform {