diff --git a/Cargo.toml b/Cargo.toml index 482f978..93392e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +glam = "0.20" +legion = "0.4.0" rayon = "1" strum = { version = "0.24", features = ["derive"] } diff --git a/src/handle.rs b/src/handle.rs new file mode 100644 index 0000000..af1383d --- /dev/null +++ b/src/handle.rs @@ -0,0 +1,18 @@ +#[repr(C)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub struct MeshHandle { + pub group_id: usize, + pub sub_id: usize, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub struct TextureHandle { + pub id: usize, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub struct MaterialHandle { + pub id: usize, +} diff --git a/src/lib.rs b/src/lib.rs index 5f55b49..1c0d60c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,8 +5,10 @@ use rayon::prelude::*; use std::sync::{Arc, RwLock}; use strum::IntoEnumIterator; +pub mod handle; pub mod pass; pub mod phase; +pub mod scene; use pass::*; use phase::*; diff --git a/src/main.rs b/src/main.rs index abf0ee2..04eb639 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,32 @@ -use cyborg::{pass, Renderer}; +use cyborg::{pass, scene, Renderer}; +use legion::{IntoSoa, World}; +use std::sync::{Arc, RwLock}; fn main() { - let mut renderer = Renderer::default(); - let mesh_pass = pass::mesh::MeshPass::new(); - renderer.add_pass(mesh_pass); + let world = Arc::new(RwLock::new(World::default())); - renderer.render(); + world.write().unwrap().extend( + ( + vec![scene::MeshComponent {}; 1000], + vec![ + scene::TransformComponent { + transform: glam::Mat4::IDENTITY, + }; + 1000 + ], + ) + .into_soa(), + ); + + let mut renderer = Renderer::default(); + let mesh_pass = pass::mesh::MeshPass::new(world); + renderer.add_pass_arc(mesh_pass); + + let start = std::time::Instant::now(); + for n in 0..1000 { + println!("Frame #{}:", n); + renderer.render(); + } + + println!("Time elapsed: {:?}", start.elapsed()); } diff --git a/src/pass/mesh.rs b/src/pass/mesh.rs index 85038df..bf0382a 100644 --- a/src/pass/mesh.rs +++ b/src/pass/mesh.rs @@ -1,12 +1,32 @@ use super::*; +use crate::scene; +use legion::{Query, World}; +use std::sync::{Arc, Mutex, RwLock}; -pub struct FrameData {} +#[derive(Debug, Clone)] +pub struct MeshInstance { + // TODO put useful data in here + mesh: scene::MeshComponent, + transform: scene::TransformComponent, +} -pub struct MeshPass {} +#[derive(Debug, Default)] +pub struct FrameData { + meshes: Vec, +} + +pub struct MeshPass { + world: Arc>, + mesh_query: Query<( + &'static scene::MeshComponent, + &'static scene::TransformComponent, + )>, +} impl MeshPass { - pub fn new() -> Self { - Self {} + pub fn new(world: Arc>) -> Arc> { + let mesh_query = Query::new(); + Arc::new(RwLock::new(Self { world, mesh_query })) } } @@ -14,17 +34,31 @@ impl RenderPass for MeshPass { type FrameData = FrameData; fn create_frame_data(&mut self) -> FrameData { - FrameData {} + FrameData::default() } fn begin_frame(&mut self, data: &mut FrameData, phases: &mut PhaseList) { println!("MeshPass::begin_frame()"); phases.insert_pre(PrePhase::VertexSkinning); - phases.insert_viewport(ViewportPhase::Depth); phases.insert_viewport(ViewportPhase::Opaque); phases.insert_viewport(ViewportPhase::Transparent); + + let world = self.world.read().unwrap(); + let meshes = Mutex::new(Vec::new()); + self.mesh_query.par_for_each_chunk(&*world, |chunk| { + let chunk_meshes: Vec = chunk + .into_iter() + .map(|(mesh, transform)| MeshInstance { + mesh: mesh.to_owned(), + transform: transform.to_owned(), + }) + .collect(); + meshes.lock().unwrap().extend_from_slice(&chunk_meshes); + }); + + data.meshes = meshes.into_inner().unwrap(); } fn render_pre(&self, phase: PrePhase, data: &FrameData, cmds: &mut gpu::RenderBundleEncoder) { diff --git a/src/scene.rs b/src/scene.rs new file mode 100644 index 0000000..0ea9859 --- /dev/null +++ b/src/scene.rs @@ -0,0 +1,28 @@ +use crate::handle; + +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct MeshComponent { + // TODO resource pools + // pub mesh_handle: handle::MeshHandle, + // pub material_handle: handle::MaterialHandle, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct PointLightComponent { + pub intensity: glam::Vec3A, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct PositionComponent { + pub position: glam::Vec3A, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct OrientationComponent { + pub orientation: glam::Quat, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct TransformComponent { + pub transform: glam::Mat4, +}