diff --git a/src/ecs/components/mesh.rs b/src/ecs/components/mesh.rs index b169c63..6612ea6 100755 --- a/src/ecs/components/mesh.rs +++ b/src/ecs/components/mesh.rs @@ -1,18 +1,16 @@ use edict::Component; -use crate::render::{vertex::Vertex, mesh::Mesh, material::Material}; +use lyra_resource::Mesh; #[derive(Clone, Component)] pub struct MeshComponent { pub mesh: Mesh, - pub material: Material, } impl MeshComponent { - pub fn new(mesh: Mesh, material: Material) -> Self { + pub fn new(mesh: Mesh) -> Self { Self { mesh, - material } } } \ No newline at end of file diff --git a/src/ecs/components/model.rs b/src/ecs/components/model.rs index 5f68790..b50b3de 100644 --- a/src/ecs/components/model.rs +++ b/src/ecs/components/model.rs @@ -1,22 +1,22 @@ -use crate::assets::{Model, Resource}; +use lyra_resource::ResHandle; -use std::sync::Arc; +use crate::assets::Model; #[derive(Clone, edict::Component)] -pub struct ModelComponent(pub Arc>); +pub struct ModelComponent(pub ResHandle); -impl From>> for ModelComponent { - fn from(value: Arc>) -> Self { +impl From> for ModelComponent { + fn from(value: ResHandle) -> Self { ModelComponent(value) } } -/* impl From> for ModelComponent { +/* impl From for ModelComponent { } */ impl std::ops::Deref for ModelComponent { - type Target = Arc>; + type Target = ResHandle; fn deref(&self) -> &Self::Target { &self.0 diff --git a/src/render/render_job.rs b/src/render/render_job.rs index c331039..a7000aa 100755 --- a/src/render/render_job.rs +++ b/src/render/render_job.rs @@ -2,11 +2,11 @@ use edict::EntityId; use crate::math::Transform; -use super::{mesh::Mesh, material::Material}; +//use super::mesh::Mesh; +use lyra_resource::Mesh; pub struct RenderJob { mesh: Mesh, - material: Material, entity: EntityId, transform: Transform, @@ -14,10 +14,9 @@ pub struct RenderJob { } impl RenderJob { - pub fn new(mesh: Mesh, material: Material, entity: EntityId, transform: Transform, last_transform: Option) -> Self { + pub fn new(mesh: Mesh, entity: EntityId, transform: Transform, last_transform: Option) -> Self { Self { mesh, - material, entity, transform, last_transform, @@ -28,10 +27,6 @@ impl RenderJob { &self.mesh } - pub fn material(&self)-> &Material { - &self.material - } - pub fn entity(&self)-> EntityId { self.entity } diff --git a/src/render/renderer.rs b/src/render/renderer.rs index 0d1aec1..ab01d2f 100755 --- a/src/render/renderer.rs +++ b/src/render/renderer.rs @@ -5,30 +5,25 @@ use std::num::NonZeroU64; use std::sync::Arc; use std::borrow::Cow; -use aligned_vec::AVec; -use async_std::sync::Mutex; -use async_trait::async_trait; - -use atomicell::{AtomicCell, RefMut}; use edict::query::EpochOf; use edict::{EntityId, Entities}; -use glam::Mat4; +use glam::Vec3; use tracing::{debug, warn}; -use wgpu::{BindGroup, BindGroupLayout, Limits, BufferBinding}; +use wgpu::{BindGroup, BindGroupLayout, Limits}; use wgpu::util::DeviceExt; use winit::window::Window; use crate::ecs::components::camera::CameraComponent; use crate::ecs::components::mesh::MeshComponent; +use crate::ecs::components::model::ModelComponent; use crate::ecs::components::transform::TransformComponent; -use crate::math::{Transform, Angle}; -use crate::resources; use super::camera::RenderCamera; use super::desc_buf_lay::DescVertexBufferLayout; use super::texture::RenderTexture; -use super::vertex::Vertex; -use super::{render_pipeline::FullRenderPipeline, render_buffer::BufferStorage, render_job::RenderJob, mesh::Mesh}; +use super::{render_pipeline::FullRenderPipeline, render_buffer::BufferStorage, render_job::RenderJob}; + +use lyra_resource::Mesh; pub trait Renderer { fn prepare(&mut self, main_world: &mut edict::World); @@ -36,7 +31,7 @@ pub trait Renderer { fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize); fn surface_size(&self) -> winit::dpi::PhysicalSize; - fn add_render_pipeline(&mut self, shader_id: u32, pipeline: Arc); + fn add_render_pipeline(&mut self, shader_id: u64, pipeline: Arc); } struct RenderBufferStorage { @@ -145,7 +140,7 @@ pub struct BasicRenderer { pub clear_color: wgpu::Color, - pub render_pipelines: HashMap>, + pub render_pipelines: HashMap>, pub render_jobs: VecDeque, buffer_storage: HashMap, // TODO: clean up left over buffers from deleted entities/components @@ -391,13 +386,13 @@ impl BasicRenderer { } // TODO: minimize how often model buffers are updated by checking if they changed - fn update_model_buffers(&mut self, entity: EntityId, model: &MeshComponent) { + fn update_mesh_buffers(&mut self, entity: EntityId, mesh: &Mesh) { if let Some(buffers) = self.buffer_storage.get_mut(&entity) { // check if the buffer sizes dont match. If they dont, completely remake the buffers - let vertices = &model.mesh.vertices; + let vertices = mesh.position().unwrap(); if buffers.buffer_vertex.count() != vertices.len() { drop(buffers); - let (vert, idx) = self.create_vertex_index_buffers(&model.mesh); + let (vert, idx) = self.create_vertex_index_buffers(mesh); // have to re-get buffers because of borrow checker let buffers = self.buffer_storage.get_mut(&entity).unwrap(); @@ -411,14 +406,14 @@ impl BasicRenderer { let vertex_buffer = buffers.buffer_vertex.buffer(); let vertices = vertices.as_slice(); // align the vertices to 4 bytes (u32 is 4 bytes, which is wgpu::COPY_BUFFER_ALIGNMENT) - let (_, vertices, _) = bytemuck::pod_align_to::(vertices); + let (_, vertices, _) = bytemuck::pod_align_to::(vertices); self.queue.write_buffer(&vertex_buffer, 0, bytemuck::cast_slice(&vertices)); // update the indices if they're given if let Some(index_buffer) = buffers.buffer_indices.as_ref() { let index_buffer = index_buffer.buffer(); - let indices = model.mesh.indices.as_ref().unwrap().as_slice(); - let (_, indices, _) = bytemuck::pod_align_to::(indices); + let indices = mesh.indices.as_ref().unwrap().as_slice(); + let (_, indices, _) = bytemuck::pod_align_to::(indices); // TODO: Don't force indicies into u32 self.queue.write_buffer(index_buffer, 0, bytemuck::cast_slice(&indices)); } @@ -426,14 +421,15 @@ impl BasicRenderer { } fn create_vertex_index_buffers(&mut self, mesh: &Mesh) -> (BufferStorage, Option) { + let vertices = mesh.position().unwrap(); let vertex_buffer = self.device.create_buffer_init( &wgpu::util::BufferInitDescriptor { label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(mesh.vertices.as_slice()), + contents: bytemuck::cast_slice(vertices.as_slice()), usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages:: COPY_DST, } ); - let vertex_buffer = BufferStorage::new(vertex_buffer, 0, mesh.vertices.len()); + let vertex_buffer = BufferStorage::new(vertex_buffer, 0, vertices.len()); let buffer_indices = match mesh.indices.as_ref() { Some(indices) => { @@ -457,63 +453,66 @@ impl BasicRenderer { ( vertex_buffer, buffer_indices ) } - fn create_model_buffers(&mut self, model: &MeshComponent, transform_indices: TransformBufferIndices) -> RenderBufferStorage { - let mesh = &model.mesh; - + fn create_mesh_buffers(&mut self, mesh: &Mesh, transform_indices: TransformBufferIndices) -> RenderBufferStorage { let (vertex_buffer, buffer_indices) = self.create_vertex_index_buffers(mesh); - let model_texture = &model.material.texture; - let image = &model_texture.data.as_ref().unwrap().image; - let diffuse_texture = RenderTexture::from_image(&self.device, &self.queue, image, None).unwrap(); + let (diffuse_layout, diffuse_bindgroup) = if let Some(model_texture) = &mesh.material().texture { + let image = &model_texture.data.as_ref().unwrap().image; + let diffuse_texture = RenderTexture::from_image(&self.device, &self.queue, image, None).unwrap(); - let texture_bind_group_layout = - self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, + let texture_bind_group_layout = + self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + }, + count: None, }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - // This should match the filterable field of the - // corresponding Texture entry above. - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - label: Some("texture_bind_group_layout"), - }); + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + // This should match the filterable field of the + // corresponding Texture entry above. + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + ], + label: Some("texture_bind_group_layout"), + }); - let diffuse_bind_group = self.device.create_bind_group( - &wgpu::BindGroupDescriptor { - layout: &texture_bind_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(diffuse_texture.view()), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(diffuse_texture.sampler()), - } - ], - label: Some("diffuse_bind_group"), - } - ); + let diffuse_bind_group = self.device.create_bind_group( + &wgpu::BindGroupDescriptor { + layout: &texture_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(diffuse_texture.view()), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(diffuse_texture.sampler()), + } + ], + label: Some("diffuse_bind_group"), + } + ); + + (Some(texture_bind_group_layout), Some(diffuse_bind_group)) + } else { + (None, None) + }; RenderBufferStorage { buffer_vertex: vertex_buffer, buffer_indices, render_texture: None, - texture_layout: None, - texture_bindgroup: Some(diffuse_bind_group), + texture_layout: diffuse_layout, + texture_bindgroup: diffuse_bindgroup, transform_index: transform_indices } } @@ -561,9 +560,13 @@ impl Renderer for BasicRenderer { let mut alive_entities = HashSet::new(); - for (entity, model, model_epoch, transform) in main_world.query::<(Entities, &MeshComponent, EpochOf, &TransformComponent)>().iter() { + for (entity, model, model_epoch, transform) in main_world.query::<(Entities, &ModelComponent, EpochOf, &TransformComponent)>().iter() { + debug!("Collecting model things"); + let model = model.data.as_ref().unwrap().as_ref(); + let model_mesh = model.meshes.first().unwrap(); + // Create the render job and push it to the queue - let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform.transform, None); + let job = RenderJob::new(model_mesh.clone(), entity, transform.transform, None); self.render_jobs.push_back(job); alive_entities.insert(entity); @@ -579,7 +582,7 @@ impl Renderer for BasicRenderer { entity, transform.transform.calculate_mat4()); // create the mesh's buffers - let buffers = self.create_model_buffers(model, indices); + let buffers = self.create_mesh_buffers(model_mesh, indices); self.buffer_storage.insert(entity, buffers); } else { // update entity transforms @@ -588,11 +591,15 @@ impl Renderer for BasicRenderer { // if the model was updated, update its buffers if model_epoch == last_epoch { - self.update_model_buffers(entity, model); + self.update_mesh_buffers(entity, model_mesh); } } } + for (entity, mesh, mesh_epoch, transform) in main_world.query::<(Entities, &MeshComponent, EpochOf, &TransformComponent)>().iter() { + debug!("TODO: Process MeshComponents"); // TODO: Process MeshComponents + } + // collect dead entities self.transform_buffers.tick(); @@ -642,9 +649,11 @@ impl Renderer for BasicRenderer { }), }); + debug!("Executing {} render jobs", self.render_jobs.len()); + // Pop off jobs from the queue as they're being processed while let Some(job) = self.render_jobs.pop_front() { - if let Some(pipeline) = self.render_pipelines.get(&job.material().shader_id) { + if let Some(pipeline) = self.render_pipelines.get(&job.mesh().material().shader_uuid.unwrap_or(0)) { // specify to use this pipeline render_pass.set_pipeline(pipeline.get_wgpu_pipeline()); @@ -674,11 +683,13 @@ impl Renderer for BasicRenderer { render_pass.set_index_buffer(indices.buffer().slice(..), wgpu::IndexFormat::Uint16); render_pass.draw_indexed(0..indices_len, 0, 0..1); } else { + let vertices = mesh.position().unwrap(); + render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..)); - render_pass.draw(0..mesh.vertices.len() as u32, 0..1); + render_pass.draw(0..vertices.len() as u32, 0..1); } } else { - warn!("Failure to find RenderPipeline with shader id of '{}'!", job.material().shader_id); + warn!("Failure to find RenderPipeline with shader id of '{}'!", job.mesh().material().shader_uuid.unwrap_or(0)); } } } @@ -706,7 +717,7 @@ impl Renderer for BasicRenderer { self.size } - fn add_render_pipeline(&mut self, shader_id: u32, pipeline: Arc) { + fn add_render_pipeline(&mut self, shader_id: u64, pipeline: Arc) { self.render_pipelines.insert(shader_id, pipeline); } } \ No newline at end of file