From 4ffb74180c4abea9c27e720d84211a12143e1bcd Mon Sep 17 00:00:00 2001 From: jsguay-legion Date: Wed, 29 Jun 2022 15:04:49 -0400 Subject: [PATCH 1/3] Move special-case ground plane/picked/manipulator to common display lists code --- crates/lgn-animation/src/debug_display.rs | 8 +- .../src/components/light_component.rs | 11 +- .../src/components/render_surface.rs | 148 ++++++++++- .../src/core/render_object.rs | 6 +- .../src/core/services/viewports.rs | 24 ++ .../debug_display/debug_display_manager.rs | 31 ++- .../src/debug_display/stress_test.rs | 8 +- crates/lgn-graphics-renderer/src/lib.rs | 25 +- .../src/render_context.rs | 5 +- .../src/script/render_passes/debug_pass.rs | 243 +++--------------- .../src/surface_renderer.rs | 32 ++- crates/lgn-physics/src/debug_display.rs | 25 +- 12 files changed, 297 insertions(+), 269 deletions(-) diff --git a/crates/lgn-animation/src/debug_display.rs b/crates/lgn-animation/src/debug_display.rs index bfadcc911d..3d46ec62fa 100644 --- a/crates/lgn-animation/src/debug_display.rs +++ b/crates/lgn-animation/src/debug_display.rs @@ -4,7 +4,10 @@ use crate::{ }; use lgn_ecs::prelude::{Query, Res}; use lgn_graphics_data::Color; -use lgn_graphics_renderer::{debug_display::DebugDisplay, resources::DefaultMeshType}; +use lgn_graphics_renderer::{ + debug_display::{DebugDisplay, DebugPrimitiveMaterial, DebugPrimitiveType}, + resources::DefaultMeshType, +}; pub(crate) fn display_animation( debug_display: Res<'_, DebugDisplay>, @@ -42,8 +45,9 @@ pub(crate) fn display_animation( let debug_color = Color::new(bone_depth * color_interval, 255, 52, 255); builder.add_default_mesh( &clip.poses[clip.current_key_frame_index].transforms[n_bone].global, - DefaultMeshType::Sphere, + DebugPrimitiveType::default_mesh(DefaultMeshType::Sphere), debug_color, + DebugPrimitiveMaterial::WireDepth, ); } } diff --git a/crates/lgn-graphics-renderer/src/components/light_component.rs b/crates/lgn-graphics-renderer/src/components/light_component.rs index 452f29ee33..0d1096404d 100644 --- a/crates/lgn-graphics-renderer/src/components/light_component.rs +++ b/crates/lgn-graphics-renderer/src/components/light_component.rs @@ -10,7 +10,7 @@ use crate::{ InsertRenderObjectCommand, PrimaryTableCommandBuilder, PrimaryTableView, RemoveRenderObjectCommand, RenderObjectId, UpdateRenderObjectCommand, }, - debug_display::DebugDisplay, + debug_display::{DebugDisplay, DebugPrimitiveMaterial, DebugPrimitiveType}, lighting::RenderLight, resources::DefaultMeshType, }; @@ -170,8 +170,9 @@ pub(crate) fn tmp_debug_display_lights( .with_translation(transform.translation) .with_scale(Vec3::new(0.2, 0.2, 0.2)) // assumes the size of sphere 1.0. Needs to be scaled in order to match picking silhouette .with_rotation(transform.rotation), - DefaultMeshType::Sphere, + DebugPrimitiveType::default_mesh(DefaultMeshType::Sphere), Color::WHITE, + DebugPrimitiveMaterial::WireDepth, ); match light.light_type { LightType::Directional => { @@ -182,8 +183,9 @@ pub(crate) fn tmp_debug_display_lights( - transform.rotation.mul_vec3(Vec3::new(0.0, 0.0, 0.3)), // assumes arrow length to be 0.3 ) .with_rotation(transform.rotation), - DefaultMeshType::Arrow, + DebugPrimitiveType::default_mesh(DefaultMeshType::Arrow), Color::WHITE, + DebugPrimitiveMaterial::WireDepth, ); } LightType::Spot => { @@ -195,8 +197,9 @@ pub(crate) fn tmp_debug_display_lights( ) .with_scale(Vec3::new(factor, factor, 1.0)) .with_rotation(transform.rotation), - DefaultMeshType::Cone, + DebugPrimitiveType::default_mesh(DefaultMeshType::Cone), Color::WHITE, + DebugPrimitiveMaterial::WireDepth, ); } LightType::OmniDirectional => (), diff --git a/crates/lgn-graphics-renderer/src/components/render_surface.rs b/crates/lgn-graphics-renderer/src/components/render_surface.rs index fc6cbfce17..202990758f 100644 --- a/crates/lgn-graphics-renderer/src/components/render_surface.rs +++ b/crates/lgn-graphics-renderer/src/components/render_surface.rs @@ -2,12 +2,16 @@ use std::collections::hash_map::{Values, ValuesMut}; use std::hash::Hash; use std::{cmp::max, sync::Arc}; -use lgn_ecs::prelude::{Query, ResMut}; +use lgn_ecs::prelude::{Query, ResMut, With}; +use lgn_ecs::system::Res; use lgn_graphics_api::{ CmdCopyTextureParams, CommandBuffer, DeviceContext, Extents2D, Extents3D, Format, MemoryUsage, Offset2D, Offset3D, PlaneSlice, ResourceFlags, ResourceState, ResourceUsage, Semaphore, SemaphoreDef, Texture, TextureBarrier, TextureDef, TextureTiling, TextureView, TextureViewDef, }; +use lgn_graphics_data::Color; +use lgn_math::Vec3; +use lgn_transform::prelude::GlobalTransform; use lgn_window::WindowId; use parking_lot::RwLock; use std::collections::HashMap; @@ -15,13 +19,16 @@ use uuid::Uuid; use crate::core::{ as_render_object, InsertRenderObjectCommand, PrimaryTableCommandBuilder, PrimaryTableView, - RemoveRenderObjectCommand, RenderObjectId, RenderViewport, RenderViewportRendererData, - UpdateRenderObjectCommand, Viewport, ViewportId, + RemoveRenderObjectCommand, RenderCamera, RenderObjectId, RenderObjects, RenderViewport, + RenderViewportRendererData, UpdateRenderObjectCommand, Viewport, ViewportId, }; +use crate::debug_display::{DebugDisplay, DebugPrimitiveMaterial, DebugPrimitiveType}; +use crate::picking::ManipulatorManager; use crate::render_pass::PickingRenderPass; +use crate::resources::{DefaultMeshType, MeshManager}; use crate::{RenderContext, Renderer}; -use super::CameraComponent; +use super::{CameraComponent, ManipulatorComponent, PickedComponent, VisualComponent}; pub trait Presenter: Send + Sync { fn resize(&mut self, device_context: &DeviceContext, extents: RenderSurfaceExtents); @@ -669,3 +676,136 @@ pub(crate) fn reflect_viewports( } } } + +#[allow(clippy::needless_pass_by_value)] +pub fn build_display_lists( + renderer: Res<'_, Renderer>, + render_surfaces: ResMut<'_, RenderSurfaces>, + debug_display: ResMut<'_, DebugDisplay>, + picked_drawables: Query<'_, '_, (&VisualComponent, &GlobalTransform), With>, + manipulator_drawables: Query<'_, '_, (&GlobalTransform, &ManipulatorComponent)>, +) { + for render_surface in render_surfaces.iter() { + for viewport in render_surface.viewports() { + if viewport.options().ground_plane_enabled { + debug_display.create_display_list(|builder| { + builder.add_default_mesh( + &GlobalTransform::identity(), + DebugPrimitiveType::default_mesh(DefaultMeshType::GroundPlane), + Color::BLACK, + DebugPrimitiveMaterial::WireDepth, + ); + }); + } + + if viewport.options().picked_enabled { + let mesh_manager = renderer.render_resources().get::(); + let mesh_reader = mesh_manager.read(); + for (visual_component, transform) in &picked_drawables { + let render_model = visual_component.render_model_handle(); + let render_model = render_model.get().unwrap(); + + for mesh in render_model.mesh_instances() { + let mesh_id = mesh.mesh_id; + let mesh = mesh_reader.get_render_mesh(mesh_id); + + let mut min_bound = Vec3::new(f32::MAX, f32::MAX, f32::MAX); + let mut max_bound = Vec3::new(f32::MIN, f32::MIN, f32::MIN); + + for position in &mesh.positions { + let world_pos = transform.mul_vec3(*position); + + min_bound = min_bound.min(world_pos); + max_bound = max_bound.max(world_pos); + } + + let delta = max_bound - min_bound; + let mid_point = min_bound + delta * 0.5; + + let aabb_transform = GlobalTransform::identity() + .with_translation(mid_point) + .with_scale(delta); + + debug_display.create_display_list(|builder| { + builder.add_default_mesh( + &aabb_transform, + DebugPrimitiveType::default_mesh(DefaultMeshType::WireframeCube), + Color::WHITE, + DebugPrimitiveMaterial::WireDepth, + ); + builder.add_default_mesh( + transform, + DebugPrimitiveType::mesh(mesh_id), + Color::new(0, 127, 127, 127), + DebugPrimitiveMaterial::SolidDepth, + ); + }); + } + } + } + + if viewport.options().manipulators_enabled { + let render_objects = renderer.render_resources().get::(); + let viewport_primary_table = render_objects.primary_table::(); + let camera_primary_table = render_objects.primary_table::(); + + // TODO(jsg) we need to make a display list specific to one viewport. Otherwise we will see the + // manipulators for all viewports in every viewport. + let render_viewport_id = viewport.render_object_id(); + if render_viewport_id.is_none() { + continue; + } + let render_viewport_id = render_viewport_id.unwrap(); + let render_viewport = + viewport_primary_table.try_get::(render_viewport_id); + if render_viewport.is_none() { + continue; + } + let render_viewport = render_viewport.unwrap(); + + let render_camera_id = render_viewport.camera_id(); + if render_camera_id.is_none() { + continue; + } + let render_camera_id = render_camera_id.unwrap(); + let render_camera = camera_primary_table.try_get::(render_camera_id); + if render_camera.is_none() { + continue; + } + let render_camera = render_camera.unwrap(); + + for (transform, manipulator) in &manipulator_drawables { + if manipulator.active { + let view_transform = render_camera.view_transform(); + let projection = render_camera.build_projection( + render_viewport.extents().width as f32, + render_viewport.extents().height as f32, + ); + let scaled_xform = ManipulatorManager::scale_manipulator_for_viewport( + transform, + &manipulator.local_transform, + projection, + &view_transform, + ); + + let mut color = if manipulator.selected { + Color::YELLOW + } else { + manipulator.color + }; + color.a = if manipulator.transparent { 225 } else { 255 }; + + debug_display.create_display_list(|builder| { + builder.add_default_mesh( + &scaled_xform, + DebugPrimitiveType::default_mesh(manipulator.default_mesh_type), + color, + DebugPrimitiveMaterial::SolidNoDepth, + ); + }); + } + } + } + } + } +} diff --git a/crates/lgn-graphics-renderer/src/core/render_object.rs b/crates/lgn-graphics-renderer/src/core/render_object.rs index 0d368e4193..1ec49c8a45 100644 --- a/crates/lgn-graphics-renderer/src/core/render_object.rs +++ b/crates/lgn-graphics-renderer/src/core/render_object.rs @@ -526,12 +526,14 @@ impl PrimaryTable { let generation = id.generation; assert!( self.set.borrow().allocated.contains(index), - "RenderObject index {} not allocated.", + "RenderObject of type {} index {} not allocated.", + self.key.type_name, index ); assert!( self.set.borrow().generations[index] == generation, - "RenderObject index {} generation mismatch (expected {} got {})", + "RenderObject of type {} index {} generation mismatch (expected {} got {})", + self.key.type_name, index, self.set.borrow().generations[index], generation diff --git a/crates/lgn-graphics-renderer/src/core/services/viewports.rs b/crates/lgn-graphics-renderer/src/core/services/viewports.rs index 8d167cf476..03617e57ea 100644 --- a/crates/lgn-graphics-renderer/src/core/services/viewports.rs +++ b/crates/lgn-graphics-renderer/src/core/services/viewports.rs @@ -4,6 +4,7 @@ use lgn_graphics_api::{ ResourceUsage, StoreOp, Texture, TextureBarrier, TextureDef, TextureTiling, TextureView, TextureViewDef, ViewDimension, }; + use uuid::Uuid; use crate::core::{RenderObjectId, SecondaryTableHandler}; @@ -17,11 +18,29 @@ impl ViewportId { } } +#[derive(Clone)] +pub struct ViewportOptions { + pub ground_plane_enabled: bool, + pub picked_enabled: bool, + pub manipulators_enabled: bool, +} + +impl Default for ViewportOptions { + fn default() -> Self { + Self { + ground_plane_enabled: true, + picked_enabled: true, + manipulators_enabled: true, + } + } +} + #[derive(Clone)] pub struct Viewport { id: ViewportId, offset: Offset2D, extents: Extents2D, + options: ViewportOptions, camera_id: Option, render_object_id: Option, } @@ -32,6 +51,7 @@ impl Viewport { id: ViewportId::new(), offset, extents, + options: ViewportOptions::default(), camera_id: None, render_object_id: None, } @@ -71,6 +91,10 @@ impl Viewport { pub fn set_render_object_id(&mut self, render_object_id: RenderObjectId) { self.render_object_id = Some(render_object_id); } + + pub fn options(&self) -> &ViewportOptions { + &self.options + } } #[derive(Debug)] diff --git a/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs b/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs index 3ac7092099..3f85a29d3a 100644 --- a/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs +++ b/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs @@ -5,7 +5,7 @@ use lgn_tracing::span_fn; use lgn_transform::components::GlobalTransform; use std::sync::Mutex; -use crate::resources::DefaultMeshType; +use crate::resources::{DefaultMeshType, RenderMeshId}; pub struct DebugDisplay { display_lists: Mutex>, @@ -61,13 +61,15 @@ impl<'system> DisplayListBuilder<'system> { pub fn add_default_mesh( &mut self, transform: &GlobalTransform, - default_mesh_type: DefaultMeshType, + primitive_type: DebugPrimitiveType, color: Color, + material: DebugPrimitiveMaterial, ) { let primitive = DebugPrimitive { - primitive_type: DebugPrimitiveType::DefaultMesh { default_mesh_type }, + primitive_type, transform: *transform, color, + material, }; self.display_list.primitives.push(primitive); } @@ -78,14 +80,31 @@ pub struct DisplayList { } pub enum DebugPrimitiveType { - // TODO(vdbdd): add those new types - // DisplayList - // Mesh + Mesh { mesh_id: RenderMeshId }, DefaultMesh { default_mesh_type: DefaultMeshType }, } +impl DebugPrimitiveType { + pub fn mesh(mesh_id: RenderMeshId) -> Self { + Self::Mesh { mesh_id } + } + + pub fn default_mesh(default_mesh_type: DefaultMeshType) -> Self { + Self::DefaultMesh { default_mesh_type } + } +} + +#[allow(clippy::enum_variant_names)] +pub enum DebugPrimitiveMaterial { + WireDepth, + SolidDepth, + WireNoDepth, + SolidNoDepth, +} + pub struct DebugPrimitive { pub primitive_type: DebugPrimitiveType, pub transform: GlobalTransform, pub color: Color, + pub material: DebugPrimitiveMaterial, } diff --git a/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs b/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs index ba4759257d..5eebeaa00b 100644 --- a/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs +++ b/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs @@ -4,7 +4,10 @@ use lgn_graphics_data::Color; use lgn_tracing::span_fn; use lgn_transform::components::GlobalTransform; -use crate::resources::DefaultMeshType; +use crate::{ + debug_display::{DebugPrimitiveMaterial, DebugPrimitiveType}, + resources::DefaultMeshType, +}; use super::DebugDisplay; @@ -22,8 +25,9 @@ pub fn add_debug_things(debug_display: Res<'_, DebugDisplay>) { for _i in 1..1000 { builder.add_default_mesh( &GlobalTransform::identity(), - DefaultMeshType::Sphere, + DebugPrimitiveType::default_mesh(DefaultMeshType::Sphere), Color::BLACK, + DebugPrimitiveMaterial::WireDepth, ); } }); diff --git a/crates/lgn-graphics-renderer/src/lib.rs b/crates/lgn-graphics-renderer/src/lib.rs index 2c8218ef04..0667669992 100644 --- a/crates/lgn-graphics-renderer/src/lib.rs +++ b/crates/lgn-graphics-renderer/src/lib.rs @@ -13,9 +13,9 @@ mod cgen { } use crate::components::{ - reflect_camera_components, reflect_viewports, reflect_visual_components, tmp_create_camera, - tmp_debug_display_lights, CameraOptions, EcsToRenderCamera, EcsToRenderLight, - EcsToRenderViewport, EcsToRenderVisual, + build_display_lists, reflect_camera_components, reflect_viewports, reflect_visual_components, + tmp_create_camera, tmp_debug_display_lights, CameraOptions, EcsToRenderCamera, + EcsToRenderLight, EcsToRenderViewport, EcsToRenderVisual, }; use crate::core::{ GPUTimelineManager, RenderCamera, RenderCommandQueuePool, RenderFeatures, @@ -95,8 +95,8 @@ use crate::gpu_renderer::{ui_mesh_renderer, MeshRenderer}; use crate::renderdoc::RenderDocManager; use crate::{ components::{ - reflect_light_components, ManipulatorComponent, PickedComponent, - RenderSurfaceCreatedForWindow, RenderSurfaceExtents, RenderSurfaces, + reflect_light_components, ManipulatorComponent, RenderSurfaceCreatedForWindow, + RenderSurfaceExtents, RenderSurfaces, }, egui::{egui_plugin::EguiPlugin, Egui}, lighting::LightingManager, @@ -118,7 +118,7 @@ use crate::resources::{ }; use crate::{ - components::{apply_camera_setups, camera_control, RenderSurface, VisualComponent}, + components::{apply_camera_setups, camera_control, RenderSurface}, labels::RendererLabel, }; @@ -426,6 +426,7 @@ impl Plugin for RendererPlugin { RenderStage::Prepare, camera_control.exclusive_system().at_start(), ); + app.add_system_to_stage(RenderStage::Prepare, build_display_lists); // // Stage: Render @@ -639,10 +640,7 @@ fn render_update( ResMut<'_, RenderSurfaces>, EventReader<'_, '_, KeyboardInput>, ), - queries: ( - Query<'_, '_, (&VisualComponent, &GlobalTransform), With>, - Query<'_, '_, (&GlobalTransform, &ManipulatorComponent)>, - ), + queries: (Query<'_, '_, (&GlobalTransform, &ManipulatorComponent)>,), ) { // resources let renderer = resources.0; @@ -654,8 +652,7 @@ fn render_update( let mut keyboard_input_events = resources.6; // queries - let q_picked_drawables = queries.0; - let q_manipulator_drawables = queries.1; + let q_manipulator_drawables = queries.0; // // Simulation thread @@ -673,9 +670,6 @@ fn render_update( } } - let picked_drawables = q_picked_drawables - .iter() - .collect::>(); let manipulator_drawables = q_manipulator_drawables .iter() .collect::>(); @@ -804,7 +798,6 @@ fn render_update( bump, &picking_manager, &debug_display, - picked_drawables.as_slice(), manipulator_drawables.as_slice(), &egui, ); diff --git a/crates/lgn-graphics-renderer/src/render_context.rs b/crates/lgn-graphics-renderer/src/render_context.rs index d44760c1f1..059c00f4a1 100644 --- a/crates/lgn-graphics-renderer/src/render_context.rs +++ b/crates/lgn-graphics-renderer/src/render_context.rs @@ -6,7 +6,7 @@ use lgn_graphics_api::{ use lgn_transform::prelude::GlobalTransform; use crate::{ - components::{ManipulatorComponent, VisualComponent}, + components::ManipulatorComponent, debug_display::DebugDisplay, egui::Egui, picking::PickingManager, @@ -29,7 +29,6 @@ pub struct RenderContext<'frame> { pub bump: &'frame Bump, pub picking_manager: &'frame PickingManager, pub debug_display: &'frame DebugDisplay, - pub picked_drawables: &'frame [(&'frame VisualComponent, &'frame GlobalTransform)], pub manipulator_drawables: &'frame [(&'frame GlobalTransform, &'frame ManipulatorComponent)], pub egui: &'frame Egui, // tmp @@ -52,7 +51,6 @@ impl<'frame> RenderContext<'frame> { bump: &'frame Bump, picking_manager: &'frame PickingManager, debug_display: &'frame DebugDisplay, - picked_drawables: &'frame [(&'frame VisualComponent, &'frame GlobalTransform)], manipulator_drawables: &'frame [(&'frame GlobalTransform, &'frame ManipulatorComponent)], egui: &'frame Egui, ) -> Self { @@ -68,7 +66,6 @@ impl<'frame> RenderContext<'frame> { bump, picking_manager, debug_display, - picked_drawables, manipulator_drawables, egui, persistent_descriptor_set: None, diff --git a/crates/lgn-graphics-renderer/src/script/render_passes/debug_pass.rs b/crates/lgn-graphics-renderer/src/script/render_passes/debug_pass.rs index 52bd4e11ba..973884af85 100644 --- a/crates/lgn-graphics-renderer/src/script/render_passes/debug_pass.rs +++ b/crates/lgn-graphics-renderer/src/script/render_passes/debug_pass.rs @@ -4,20 +4,14 @@ use lgn_graphics_api::{ }; use lgn_graphics_cgen_runtime::CGenShaderKey; use lgn_graphics_data::Color; -use lgn_math::{Vec3, Vec4}; +use lgn_math::Vec4; use lgn_transform::prelude::GlobalTransform; use crate::{ cgen::{self, cgen_type::TransformData}, - components::{ManipulatorComponent, VisualComponent}, - core::{ - RenderCamera, RenderGraphBuilder, RenderGraphLoadState, RenderGraphViewId, RenderViewport, - }, - debug_display::{DebugDisplay, DebugPrimitiveType}, - picking::ManipulatorManager, - resources::{ - DefaultMeshType, MeshManager, PipelineDef, PipelineHandle, PipelineManager, RenderMesh, - }, + core::{RenderGraphBuilder, RenderGraphLoadState, RenderGraphViewId}, + debug_display::{DebugDisplay, DebugPrimitiveMaterial, DebugPrimitiveType}, + resources::{MeshManager, PipelineDef, PipelineHandle, PipelineManager, RenderMesh}, RenderContext, }; @@ -35,7 +29,7 @@ impl DebugPass { solid_pso_depth_handle, wire_pso_depth_handle, solid_pso_no_depth_handle, - _wire_pso_no_depth_handle, + wire_pso_no_depth_handle, ) = Self::build_pso_handles(builder.pipeline_manager); builder.add_graphics_pass("Debug", |graphics_pass_builder| { @@ -50,37 +44,14 @@ impl DebugPass { cmd_buffer .cmd_bind_index_buffer(render_context.static_buffer.index_buffer_binding()); - Self::render_ground_plane( - render_context, - cmd_buffer, - &mesh_manager, - wire_pso_depth_handle, - ); - - Self::render_picked( - render_context, - cmd_buffer, - render_context.picked_drawables, - &mesh_manager, - wire_pso_depth_handle, - solid_pso_depth_handle, - ); - Self::render_debug_display( render_context, cmd_buffer, render_context.debug_display, &mesh_manager, wire_pso_depth_handle, - ); - - Self::render_manipulators( - render_context, - cmd_buffer, - render_context.manipulator_drawables, - &mesh_manager, - execute_context.debug_stuff.render_viewport, - execute_context.debug_stuff.render_camera, + solid_pso_depth_handle, + wire_pso_no_depth_handle, solid_pso_no_depth_handle, ); }) @@ -211,107 +182,46 @@ impl DebugPass { ) } - pub fn render_ground_plane( - render_context: &RenderContext<'_>, - cmd_buffer: &mut CommandBuffer, - mesh_manager: &MeshManager, - wire_pso_depth_handle: PipelineHandle, - ) { - cmd_buffer.with_label("Ground Plane", |cmd_buffer| { - if let Some(wire_pso_depth_pipeline) = render_context - .pipeline_manager - .get_pipeline(wire_pso_depth_handle) - { - cmd_buffer.cmd_bind_pipeline(wire_pso_depth_pipeline); - - render_context.bind_default_descriptor_sets(cmd_buffer); - - let mesh_reader = mesh_manager.read(); - - render_mesh( - mesh_reader.get_default_mesh(DefaultMeshType::GroundPlane), - &GlobalTransform::identity(), - Color::BLACK, - 0.0, - cmd_buffer, - ); - } - }); - } - - pub fn render_picked( + #[allow(clippy::too_many_arguments)] + pub fn render_debug_display( render_context: &RenderContext<'_>, cmd_buffer: &mut CommandBuffer, - picked_visuals: &[(&VisualComponent, &GlobalTransform)], + debug_display: &DebugDisplay, mesh_manager: &MeshManager, wire_pso_depth_handle: PipelineHandle, solid_pso_depth_handle: PipelineHandle, + wire_pso_no_depth_handle: PipelineHandle, + solid_pso_no_depth_handle: PipelineHandle, ) { - cmd_buffer.with_label("Picked", |cmd_buffer| { - if let Some(wire_pso_depth_pipeline) = render_context - .pipeline_manager - .get_pipeline(wire_pso_depth_handle) - { - if let Some(solid_pso_depth_pipeline) = render_context - .pipeline_manager - .get_pipeline(solid_pso_depth_handle) - { + cmd_buffer.with_label("Debug_Display", |cmd_buffer| { + // TODO(jsg) sort by material + debug_display.render_primitives(|primitive| { + let pso_handle = match primitive.material { + DebugPrimitiveMaterial::WireDepth => wire_pso_depth_handle, + DebugPrimitiveMaterial::SolidDepth => solid_pso_depth_handle, + DebugPrimitiveMaterial::WireNoDepth => wire_pso_no_depth_handle, + DebugPrimitiveMaterial::SolidNoDepth => solid_pso_no_depth_handle, + }; + + if let Some(pipeline) = render_context.pipeline_manager.get_pipeline(pso_handle) { + cmd_buffer.cmd_bind_pipeline(pipeline); render_context.bind_default_descriptor_sets(cmd_buffer); let mesh_reader = mesh_manager.read(); - let wireframe_cube = - mesh_reader.get_default_mesh(DefaultMeshType::WireframeCube); - // TODO(vdbdd): Fix that asap with the real model - - for (visual_component, transform) in picked_visuals.iter() { - let render_model = visual_component.render_model_handle(); - let render_model = render_model.get().unwrap(); - - for mesh in render_model.mesh_instances() { - cmd_buffer.cmd_bind_pipeline(wire_pso_depth_pipeline); - - let mesh = mesh_reader.get_render_mesh(mesh.mesh_id); - render_aabb_for_mesh(wireframe_cube, mesh, transform, cmd_buffer); - - cmd_buffer.cmd_bind_pipeline(solid_pso_depth_pipeline); + match primitive.primitive_type { + DebugPrimitiveType::DefaultMesh { default_mesh_type } => { render_mesh( - mesh, - transform, - Color::new(0, 127, 127, 127), + mesh_reader.get_default_mesh(default_mesh_type), + &primitive.transform, + primitive.color, 1.0, cmd_buffer, ); } - } - } - } - }); - } - - #[allow(clippy::too_many_arguments)] - pub fn render_debug_display( - render_context: &RenderContext<'_>, - cmd_buffer: &mut CommandBuffer, - debug_display: &DebugDisplay, - mesh_manager: &MeshManager, - wire_pso_depth_handle: PipelineHandle, - ) { - cmd_buffer.with_label("Debug_Display", |cmd_buffer| { - if let Some(pipeline) = render_context - .pipeline_manager - .get_pipeline(wire_pso_depth_handle) - { - cmd_buffer.cmd_bind_pipeline(pipeline); - - render_context.bind_default_descriptor_sets(cmd_buffer); - - debug_display.render_primitives(|primitive| { - match primitive.primitive_type { - DebugPrimitiveType::DefaultMesh { default_mesh_type } => { - let mesh_reader = mesh_manager.read(); + DebugPrimitiveType::Mesh { mesh_id } => { render_mesh( - mesh_reader.get_default_mesh(default_mesh_type), + mesh_reader.get_render_mesh(mesh_id), &primitive.transform, primitive.color, 1.0, @@ -319,97 +229,10 @@ impl DebugPass { ); } }; - }); - } + } + }); }); } - - #[allow(clippy::too_many_arguments)] - pub fn render_manipulators( - render_context: &RenderContext<'_>, - cmd_buffer: &mut CommandBuffer, - manipulator_meshes: &[(&GlobalTransform, &ManipulatorComponent)], - mesh_manager: &MeshManager, - render_viewport: &RenderViewport, - render_camera: &RenderCamera, - solid_pso_no_depth_handle: PipelineHandle, - ) { - for (transform, manipulator) in manipulator_meshes.iter() { - if manipulator.active { - cmd_buffer.with_label("Manipulator", |cmd_buffer| { - let view_transform = render_camera.view_transform(); - let projection = render_camera.build_projection( - render_viewport.extents().width as f32, - render_viewport.extents().height as f32, - ); - let scaled_xform = ManipulatorManager::scale_manipulator_for_viewport( - transform, - &manipulator.local_transform, - projection, - &view_transform, - ); - - let mut color = if manipulator.selected { - Color::YELLOW - } else { - manipulator.color - }; - color.a = if manipulator.transparent { 225 } else { 255 }; - - if let Some(pipeline) = render_context - .pipeline_manager - .get_pipeline(solid_pso_no_depth_handle) - { - cmd_buffer.cmd_bind_pipeline(pipeline); - - render_context.bind_default_descriptor_sets(cmd_buffer); - let mesh_reader = mesh_manager.read(); - render_mesh( - mesh_reader.get_default_mesh(manipulator.default_mesh_type), - &scaled_xform, - color, - 1.0, - cmd_buffer, - ); - } - }); - } - } - } -} - -fn render_aabb_for_mesh( - wire_frame_cube: &RenderMesh, - mesh: &RenderMesh, - transform: &GlobalTransform, - cmd_buffer: &mut CommandBuffer, -) { - cmd_buffer.with_label("AABB", |cmd_buffer| { - let mut min_bound = Vec3::new(f32::MAX, f32::MAX, f32::MAX); - let mut max_bound = Vec3::new(f32::MIN, f32::MIN, f32::MIN); - - for position in &mesh.positions { - let world_pos = transform.mul_vec3(*position); - - min_bound = min_bound.min(world_pos); - max_bound = max_bound.max(world_pos); - } - - let delta = max_bound - min_bound; - let mid_point = min_bound + delta * 0.5; - - let aabb_transform = GlobalTransform::identity() - .with_translation(mid_point) - .with_scale(delta); - - render_mesh( - wire_frame_cube, - &aabb_transform, - Color::WHITE, - 1.0, - cmd_buffer, - ); - }); } fn render_mesh( diff --git a/crates/lgn-graphics-renderer/src/surface_renderer.rs b/crates/lgn-graphics-renderer/src/surface_renderer.rs index b4110ae4c2..ed8fb62d3e 100644 --- a/crates/lgn-graphics-renderer/src/surface_renderer.rs +++ b/crates/lgn-graphics-renderer/src/surface_renderer.rs @@ -72,21 +72,23 @@ impl SurfaceRenderer { let viewports = render_surface.viewports(); let render_objects = render_resources.get::(); - let primary_table = render_objects.primary_table::(); - let mut secondary_table = + let viewport_primary_table = render_objects.primary_table::(); + let mut viewport_secondary_table = render_objects.secondary_table_mut::(); let camera_primary_table = render_objects.primary_table::(); for viewport in viewports { - let render_object_id = viewport.render_object_id(); - if render_object_id.is_none() { + let render_viewport_id = viewport.render_object_id(); + if render_viewport_id.is_none() { continue; } - let render_object_id = render_object_id.unwrap(); + let render_viewport_id = render_viewport_id.unwrap(); - let render_viewport = primary_table.get::(render_object_id); - let render_viewport_private_data = - secondary_table.get_mut::(render_object_id); + let render_viewport = + viewport_primary_table.get::(render_viewport_id); + let render_viewport_renderer_data = + viewport_secondary_table + .get_mut::(render_viewport_id); // // Visibility @@ -178,7 +180,7 @@ impl SurfaceRenderer { cmd_buffer.begin(); - render_viewport_private_data.clear_hzb_if_needed(cmd_buffer); + render_viewport_renderer_data.clear_hzb_if_needed(cmd_buffer); cmd_buffer.end(); @@ -192,7 +194,7 @@ impl SurfaceRenderer { .release(cmd_buffer_handle); let view = RenderView { - target: render_viewport_private_data.view_target(), + target: render_viewport_renderer_data.view_target(), }; let gpu_culling_pass = GpuCullingPass; @@ -218,8 +220,8 @@ impl SurfaceRenderer { ui_pass, egui_pass, hzb: [ - render_viewport_private_data.hzb()[0], - render_viewport_private_data.hzb()[1], + render_viewport_renderer_data.hzb()[0], + render_viewport_renderer_data.hzb()[1], ], }; @@ -272,9 +274,11 @@ impl SurfaceRenderer { for viewport in viewports { if let Some(render_object_id) = viewport.render_object_id() { - let render_viewport = primary_table.get::(render_object_id); + let render_viewport = + viewport_primary_table.get::(render_object_id); let render_viewport_private_data = - secondary_table.get::(render_object_id); + viewport_secondary_table + .get::(render_object_id); render_viewports.push(render_viewport); render_viewports_private_data.push(render_viewport_private_data); diff --git a/crates/lgn-physics/src/debug_display.rs b/crates/lgn-physics/src/debug_display.rs index 7cacaadae1..9e030ba3a5 100644 --- a/crates/lgn-physics/src/debug_display.rs +++ b/crates/lgn-physics/src/debug_display.rs @@ -1,6 +1,9 @@ use lgn_ecs::prelude::{Query, Res}; use lgn_graphics_data::Color; -use lgn_graphics_renderer::{debug_display::DebugDisplay, resources::DefaultMeshType}; +use lgn_graphics_renderer::{ + debug_display::{DebugDisplay, DebugPrimitiveMaterial, DebugPrimitiveType}, + resources::DefaultMeshType, +}; use lgn_math::prelude::Vec3; use lgn_transform::prelude::GlobalTransform; use physx::prelude::PxVec3; @@ -31,16 +34,27 @@ pub(crate) fn display_collision_geometry( .with_translation(transform.translation) .with_scale(scale) // assumes the size of sphere 1.0. Needs to be scaled in order to match picking silhouette .with_rotation(transform.rotation), - DefaultMeshType::Cube, + DebugPrimitiveType::default_mesh(DefaultMeshType::Cube), debug_color, + DebugPrimitiveMaterial::WireDepth, ); } CollisionGeometry::Capsule(_capsule_geometry) => { - builder.add_default_mesh(transform, DefaultMeshType::Cylinder, debug_color); + builder.add_default_mesh( + transform, + DebugPrimitiveType::default_mesh(DefaultMeshType::Cylinder), + debug_color, + DebugPrimitiveMaterial::WireDepth, + ); } CollisionGeometry::ConvexMesh(_convex_mesh_geometry) => {} CollisionGeometry::Plane(_plane_geometry) => { - builder.add_default_mesh(transform, DefaultMeshType::GroundPlane, debug_color); + builder.add_default_mesh( + transform, + DebugPrimitiveType::default_mesh(DefaultMeshType::GroundPlane), + debug_color, + DebugPrimitiveMaterial::WireDepth, + ); } CollisionGeometry::Sphere(sphere_geometry) => { // default sphere mesh has radius of 0.25 (diameter of 0.5) @@ -51,8 +65,9 @@ pub(crate) fn display_collision_geometry( .with_translation(transform.translation) .with_scale(Vec3::ONE * scale_factor) // assumes the size of sphere 1.0. Needs to be scaled in order to match picking silhouette .with_rotation(transform.rotation), - DefaultMeshType::Sphere, + DebugPrimitiveType::default_mesh(DefaultMeshType::Sphere), debug_color, + DebugPrimitiveMaterial::WireDepth, ); } CollisionGeometry::TriangleMesh(_triangle_mesh_geometry) => {} From 0407e1086823e38d44f7da46be6d2e2c65960c43 Mon Sep 17 00:00:00 2001 From: jsguay-legion Date: Wed, 29 Jun 2022 15:47:06 -0400 Subject: [PATCH 2/3] Renames and fix release compile --- crates/lgn-animation/src/debug_display.rs | 2 +- .../src/components/light_component.rs | 6 +++--- .../src/components/render_surface.rs | 8 ++++---- .../lgn-graphics-renderer/src/core/render_object.rs | 11 +++++++++-- .../src/debug_display/debug_display_manager.rs | 2 +- .../src/debug_display/stress_test.rs | 2 +- crates/lgn-physics/src/debug_display.rs | 8 ++++---- 7 files changed, 23 insertions(+), 16 deletions(-) diff --git a/crates/lgn-animation/src/debug_display.rs b/crates/lgn-animation/src/debug_display.rs index 3d46ec62fa..8553cb0288 100644 --- a/crates/lgn-animation/src/debug_display.rs +++ b/crates/lgn-animation/src/debug_display.rs @@ -43,7 +43,7 @@ pub(crate) fn display_animation( .try_into() .unwrap(); let debug_color = Color::new(bone_depth * color_interval, 255, 52, 255); - builder.add_default_mesh( + builder.add_draw_call( &clip.poses[clip.current_key_frame_index].transforms[n_bone].global, DebugPrimitiveType::default_mesh(DefaultMeshType::Sphere), debug_color, diff --git a/crates/lgn-graphics-renderer/src/components/light_component.rs b/crates/lgn-graphics-renderer/src/components/light_component.rs index 0d1096404d..b78d47a84f 100644 --- a/crates/lgn-graphics-renderer/src/components/light_component.rs +++ b/crates/lgn-graphics-renderer/src/components/light_component.rs @@ -165,7 +165,7 @@ pub(crate) fn tmp_debug_display_lights( debug_display.create_display_list(|builder| { for (light, transform) in lights.iter() { - builder.add_default_mesh( + builder.add_draw_call( &GlobalTransform::identity() .with_translation(transform.translation) .with_scale(Vec3::new(0.2, 0.2, 0.2)) // assumes the size of sphere 1.0. Needs to be scaled in order to match picking silhouette @@ -176,7 +176,7 @@ pub(crate) fn tmp_debug_display_lights( ); match light.light_type { LightType::Directional => { - builder.add_default_mesh( + builder.add_draw_call( &GlobalTransform::identity() .with_translation( transform.translation @@ -190,7 +190,7 @@ pub(crate) fn tmp_debug_display_lights( } LightType::Spot => { let factor = 4.0 * (light.cone_angle / 2.0).tan(); // assumes that default cone mesh has 1 to 4 ratio between radius and height - builder.add_default_mesh( + builder.add_draw_call( &GlobalTransform::identity() .with_translation( transform.translation - transform.rotation.mul_vec3(Vec3::Z), // assumes cone height to be 1.0 diff --git a/crates/lgn-graphics-renderer/src/components/render_surface.rs b/crates/lgn-graphics-renderer/src/components/render_surface.rs index 202990758f..ec04896921 100644 --- a/crates/lgn-graphics-renderer/src/components/render_surface.rs +++ b/crates/lgn-graphics-renderer/src/components/render_surface.rs @@ -689,7 +689,7 @@ pub fn build_display_lists( for viewport in render_surface.viewports() { if viewport.options().ground_plane_enabled { debug_display.create_display_list(|builder| { - builder.add_default_mesh( + builder.add_draw_call( &GlobalTransform::identity(), DebugPrimitiveType::default_mesh(DefaultMeshType::GroundPlane), Color::BLACK, @@ -727,13 +727,13 @@ pub fn build_display_lists( .with_scale(delta); debug_display.create_display_list(|builder| { - builder.add_default_mesh( + builder.add_draw_call( &aabb_transform, DebugPrimitiveType::default_mesh(DefaultMeshType::WireframeCube), Color::WHITE, DebugPrimitiveMaterial::WireDepth, ); - builder.add_default_mesh( + builder.add_draw_call( transform, DebugPrimitiveType::mesh(mesh_id), Color::new(0, 127, 127, 127), @@ -796,7 +796,7 @@ pub fn build_display_lists( color.a = if manipulator.transparent { 225 } else { 255 }; debug_display.create_display_list(|builder| { - builder.add_default_mesh( + builder.add_draw_call( &scaled_xform, DebugPrimitiveType::default_mesh(manipulator.default_mesh_type), color, diff --git a/crates/lgn-graphics-renderer/src/core/render_object.rs b/crates/lgn-graphics-renderer/src/core/render_object.rs index 1ec49c8a45..aa5911f11d 100644 --- a/crates/lgn-graphics-renderer/src/core/render_object.rs +++ b/crates/lgn-graphics-renderer/src/core/render_object.rs @@ -524,16 +524,23 @@ impl PrimaryTable { pub fn get(&self, id: RenderObjectId) -> &R { let index = id.index as usize; let generation = id.generation; + + // To avoid having to duplicate the asserts. + #[cfg(debug_assertions)] + let type_name = self.key.type_name; + #[cfg(not(debug_assertions))] + let type_name = "unknown"; + assert!( self.set.borrow().allocated.contains(index), "RenderObject of type {} index {} not allocated.", - self.key.type_name, + type_name, index ); assert!( self.set.borrow().generations[index] == generation, "RenderObject of type {} index {} generation mismatch (expected {} got {})", - self.key.type_name, + type_name, index, self.set.borrow().generations[index], generation diff --git a/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs b/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs index 3f85a29d3a..3cb983ea9d 100644 --- a/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs +++ b/crates/lgn-graphics-renderer/src/debug_display/debug_display_manager.rs @@ -58,7 +58,7 @@ pub struct DisplayListBuilder<'system> { } impl<'system> DisplayListBuilder<'system> { - pub fn add_default_mesh( + pub fn add_draw_call( &mut self, transform: &GlobalTransform, primitive_type: DebugPrimitiveType, diff --git a/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs b/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs index 5eebeaa00b..691f3e21d8 100644 --- a/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs +++ b/crates/lgn-graphics-renderer/src/debug_display/stress_test.rs @@ -23,7 +23,7 @@ pub fn debug_stress_test(app: &mut App) { pub fn add_debug_things(debug_display: Res<'_, DebugDisplay>) { debug_display.create_display_list(|builder| { for _i in 1..1000 { - builder.add_default_mesh( + builder.add_draw_call( &GlobalTransform::identity(), DebugPrimitiveType::default_mesh(DefaultMeshType::Sphere), Color::BLACK, diff --git a/crates/lgn-physics/src/debug_display.rs b/crates/lgn-physics/src/debug_display.rs index 9e030ba3a5..5160779b2e 100644 --- a/crates/lgn-physics/src/debug_display.rs +++ b/crates/lgn-physics/src/debug_display.rs @@ -29,7 +29,7 @@ pub(crate) fn display_collision_geometry( let half_extents: PxVec3 = box_geometry.halfExtents.into(); let mut scale: Vec3 = half_extents.into(); scale /= 0.25; - builder.add_default_mesh( + builder.add_draw_call( &GlobalTransform::identity() .with_translation(transform.translation) .with_scale(scale) // assumes the size of sphere 1.0. Needs to be scaled in order to match picking silhouette @@ -40,7 +40,7 @@ pub(crate) fn display_collision_geometry( ); } CollisionGeometry::Capsule(_capsule_geometry) => { - builder.add_default_mesh( + builder.add_draw_call( transform, DebugPrimitiveType::default_mesh(DefaultMeshType::Cylinder), debug_color, @@ -49,7 +49,7 @@ pub(crate) fn display_collision_geometry( } CollisionGeometry::ConvexMesh(_convex_mesh_geometry) => {} CollisionGeometry::Plane(_plane_geometry) => { - builder.add_default_mesh( + builder.add_draw_call( transform, DebugPrimitiveType::default_mesh(DefaultMeshType::GroundPlane), debug_color, @@ -60,7 +60,7 @@ pub(crate) fn display_collision_geometry( // default sphere mesh has radius of 0.25 (diameter of 0.5) let radius = sphere_geometry.radius; let scale_factor = radius / 0.25; - builder.add_default_mesh( + builder.add_draw_call( &GlobalTransform::identity() .with_translation(transform.translation) .with_scale(Vec3::ONE * scale_factor) // assumes the size of sphere 1.0. Needs to be scaled in order to match picking silhouette From b757bac0cada6b5b1b085d9c5bbb39cfcbd03f1a Mon Sep 17 00:00:00 2001 From: jsguay-legion Date: Wed, 29 Jun 2022 17:49:56 -0400 Subject: [PATCH 3/3] Add bbox to mesh data in model manager --- .../src/resources/model_manager.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/lgn-graphics-renderer/src/resources/model_manager.rs b/crates/lgn-graphics-renderer/src/resources/model_manager.rs index 6f426edfa8..1344ea5c53 100644 --- a/crates/lgn-graphics-renderer/src/resources/model_manager.rs +++ b/crates/lgn-graphics-renderer/src/resources/model_manager.rs @@ -9,6 +9,7 @@ use lgn_data_runtime::{ ResourceTypeAndId, }; +use lgn_math::Vec3; use strum::{EnumCount, IntoEnumIterator}; use uuid::uuid; @@ -130,6 +131,7 @@ pub struct MeshInstance { pub mesh_id: RenderMeshId, pub material_id: MaterialId, pub material_va: u64, + pub local_aabb: (Vec3, Vec3), } pub struct ModelInstaller { @@ -200,6 +202,7 @@ impl ModelManager { mesh_id: mesh_manager.get_default_mesh_id(default_mesh_type), material_id: default_material.material_id(), material_va: default_material.gpuheap_addr(), + local_aabb: (Vec3::new(-1.0, -1.0, -1.0), Vec3::new(1.0, 1.0, 1.0)), }], }), }); @@ -248,6 +251,15 @@ impl ModelManager { .material .as_ref() .map_or(DEFAULT_MATERIAL_RESOURCE_ID, |x| x.id()); + + let mut min_bound = Vec3::new(f32::MAX, f32::MAX, f32::MAX); + let mut max_bound = Vec3::new(f32::MIN, f32::MIN, f32::MIN); + + for position in &mesh_data.positions { + min_bound = min_bound.min(*position); + max_bound = max_bound.max(*position); + } + let mesh = mesh_data.into(); let mesh_id = self.inner.mesh_manager.install_mesh(mesh).await?; let render_material_handle = asset_registry @@ -259,6 +271,7 @@ impl ModelManager { mesh_id, material_id: render_material.material_id(), material_va: render_material.gpuheap_addr(), + local_aabb: (min_bound, max_bound), }); }