diff --git a/src/legion.rs b/src/legion.rs index 8d3cf0a..2f43faf 100644 --- a/src/legion.rs +++ b/src/legion.rs @@ -8,6 +8,7 @@ use crate::Renderer; use legion::systems::Builder; use legion::world::SubWorld; use legion::*; +use rayon::prelude::*; use std::sync::Arc; /// Initializes the Cyborg renderer within a Legion world. @@ -52,6 +53,8 @@ pub fn build_renderer(resources: &mut Resources, builder: &mut Builder) { resources.insert(debug_pass); builder.add_system(draw_transformed_meshes_system()); + builder.add_system(draw_debug_system()); + builder.add_system(draw_debug_transformed_system()); builder.add_system(render_system()); builder.add_system(present_winit_system()); } @@ -80,7 +83,7 @@ fn render( #[system] fn draw_transformed_meshes( #[resource] mesh_pass: &pass::RenderPassBox, - world: &mut SubWorld, + world: &SubWorld, query: &mut Query<&scene::TransformedMesh>, ) { let transformed: Vec<_> = query.iter(world).map(|m| m.clone()).collect(); @@ -95,3 +98,34 @@ fn draw_transformed_meshes( fn present_winit(viewport: &mut WinitViewport) { viewport.present(); } + +#[system(for_each)] +#[filter(!component::())] +fn draw_debug( + #[resource] debug_pass: &pass::RenderPassBox, + draw_list: &scene::DebugDrawList, +) { + debug_pass.add_draw_list(draw_list); +} + +#[system] +fn draw_debug_transformed( + #[resource] debug_pass: &pass::RenderPassBox, + world: &SubWorld, + query: &mut Query<(&scene::DebugDrawList, &scene::Transform)>, +) { + query.par_iter_chunks(world).for_each(|draw_list_chunk| { + let mut sub_list = scene::DebugDrawList::default(); + for (draw_list, transform) in draw_list_chunk { + let vertices_start = sub_list.vertices.len(); + sub_list.merge(draw_list); + for vertex in sub_list.vertices[vertices_start..].iter_mut() { + let position = glam::Vec3::from_slice(&vertex.position); + let transformed = transform.transform.transform_point3(position); + vertex.position = transformed.to_array(); + } + } + + debug_pass.add_draw_list(&sub_list); + }); +} diff --git a/src/main.rs b/src/main.rs index 15c843d..7bc2820 100644 --- a/src/main.rs +++ b/src/main.rs @@ -89,6 +89,20 @@ fn main() { drop(mesh_pass); + let example_debug_draw = cyborg::scene::DebugDrawList { + vertices: vec![ + cyborg::scene::DebugVertex { + position: [0.0, 0.0, -0.5], + color: [1.0, 0.0, 0.0], + }, + cyborg::scene::DebugVertex { + position: [0.0, 0.0, 0.5], + color: [0.0, 0.0, 1.0], + }, + ], + indices: vec![0, 1], + }; + let r = 4; for x in -r..r { for y in -r..r { @@ -100,7 +114,8 @@ fn main() { transform, mesh: example_mesh.clone(), }, - (), + cyborg::scene::Transform { transform }, + example_debug_draw.clone(), )); } } diff --git a/src/pass/debug.rs b/src/pass/debug.rs index 114b6dd..ca65a2e 100644 --- a/src/pass/debug.rs +++ b/src/pass/debug.rs @@ -1,8 +1,9 @@ use super::*; +use crate::scene::{DebugIndex as Index, DebugVertex as Vertex, DebugDrawList}; use crate::storage::GpuVec; use crate::viewport::ViewportInfo; use crate::RenderLayouts; -use crate::scene::{DebugVertex as Vertex, DebugIndex as Index}; +use parking_lot::RwLock; pub struct FrameData { vertices: GpuVec, @@ -13,6 +14,7 @@ pub struct DebugPass { device: Arc, pipeline: wgpu::RenderPipeline, target_info: ViewportInfo, + draw_list: RwLock, } impl DebugPass { @@ -75,8 +77,13 @@ impl DebugPass { device, pipeline, target_info, + draw_list: Default::default(), } } + + pub fn add_draw_list(&self, draw_list: &DebugDrawList) { + self.draw_list.write().merge(draw_list); + } } impl RenderPass for DebugPass { @@ -104,21 +111,15 @@ impl RenderPass for DebugPass { fn begin_frame(&self, data: &mut FrameData, phases: &mut Vec, queue: &wgpu::Queue) { phases.push(Phase::Overlay); - data.vertices.clear(); - data.indices.clear(); + use std::mem::replace; + use std::ops::DerefMut; - data.vertices.extend_from_slice(&[ - Vertex { - position: [0.0, 0.0, -1.0], - color: [1.0, 0.0, 0.0], - }, - Vertex { - position: [0.0, 0.0, 1.0], - color: [0.0, 0.0, 1.0], - }, - ]); + let mut draw_list_lock = self.draw_list.write(); + let vertices = replace(&mut draw_list_lock.vertices, Default::default()); + let indices = replace(&mut draw_list_lock.indices, Default::default()); - data.indices.extend_from_slice(&[0u32, 1u32]); + let _ = replace(data.vertices.deref_mut(), vertices); + let _ = replace(data.indices.deref_mut(), indices); data.vertices.write(queue); data.indices.write(queue); diff --git a/src/scene.rs b/src/scene.rs index ab73522..1f4f2f2 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -7,6 +7,12 @@ use crate::storage::mesh::MeshHandle; use parking_lot::RwLock; use std::sync::Arc; +#[derive(Clone, Debug)] +pub struct Transform { + pub transform: glam::Mat4, +} + +// TODO split into separate transform and mesh handle components #[derive(Clone, Debug)] pub struct TransformedMesh { pub transform: glam::Mat4, @@ -42,14 +48,23 @@ impl DebugVertex { pub type DebugIndex = u32; -pub struct DebugDraw { +#[derive(Clone, Default)] +pub struct DebugDrawList { pub vertices: Vec, pub indices: Vec, } -#[derive(Default)] -pub struct DebugDraws { - pub draws: Vec, -} +impl DebugDrawList { + pub fn merge(&mut self, other: &Self) { + self.vertices.extend_from_slice(&other.vertices); -pub type DebugDrawsHandle = Arc>; + let is_offset = self.indices.len(); + self.indices.reserve(is_offset + other.indices.len()); + + for index in other.indices.iter() { + if *index < (other.vertices.len() as DebugIndex) { + self.indices.push(index + is_offset as DebugIndex); + } + } + } +}