From 0dc563e5640767257dab27e19f4d58e16838ce28 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 23 Mar 2023 16:39:51 +0100 Subject: [PATCH] Size boosted outlines for points & lines, color & size tweaking (#1667) * boost size of points in outline mask * thinner outlines in viewer * wip line size boost * fix point_size_to_world called incorrectly * outline boost for lines working now * final touches to colors, widths etc. * missing doc strings * added todo note on missing outline boost * Fix outline gaps in line strips * comment fix and world_size_from_point_size rename --- crates/re_renderer/examples/2d.rs | 2 +- crates/re_renderer/examples/depth_cloud.rs | 2 +- crates/re_renderer/examples/multiview.rs | 2 +- crates/re_renderer/shader/depth_cloud.wgsl | 3 +- crates/re_renderer/shader/lines.wgsl | 25 +++++-- crates/re_renderer/shader/point_cloud.wgsl | 8 ++- crates/re_renderer/shader/utils/size.wgsl | 7 +- .../re_renderer/shader/utils/sphere_quad.wgsl | 5 +- crates/re_renderer/src/line_strip_builder.rs | 36 +++++++++- crates/re_renderer/src/point_cloud_builder.rs | 14 +++- crates/re_renderer/src/renderer/lines.rs | 71 +++++++++++++++++-- .../re_renderer/src/renderer/point_cloud.rs | 70 ++++++++++++++++-- .../src/ui/view_spatial/scene/picking.rs | 1 - .../src/ui/view_spatial/scene/primitives.rs | 13 ++-- crates/re_viewer/src/ui/view_spatial/ui.rs | 7 +- 15 files changed, 224 insertions(+), 42 deletions(-) diff --git a/crates/re_renderer/examples/2d.rs b/crates/re_renderer/examples/2d.rs index 047c37dfbe51..cb4c25035645 100644 --- a/crates/re_renderer/examples/2d.rs +++ b/crates/re_renderer/examples/2d.rs @@ -67,7 +67,7 @@ impl framework::Example for Render2D { splits[0].resolution_in_pixel[1] as f32, ); - let mut line_strip_builder = LineStripSeriesBuilder::<()>::default(); + let mut line_strip_builder = LineStripSeriesBuilder::<()>::new(re_ctx); // Blue rect outline around the bottom right quarter. { diff --git a/crates/re_renderer/examples/depth_cloud.rs b/crates/re_renderer/examples/depth_cloud.rs index 67cf08528b7b..755422a4f17f 100644 --- a/crates/re_renderer/examples/depth_cloud.rs +++ b/crates/re_renderer/examples/depth_cloud.rs @@ -305,7 +305,7 @@ impl framework::Example for RenderDepthClouds { let world_from_model = rotation * translation_center * scale; let frame_draw_data = { - let mut builder = LineStripSeriesBuilder::<()>::default(); + let mut builder = LineStripSeriesBuilder::<()>::new(re_ctx); { let mut line_batch = builder.batch("frame").world_from_obj(world_from_model); line_batch.add_box_outline(glam::Affine3A::from_scale_rotation_translation( diff --git a/crates/re_renderer/examples/multiview.rs b/crates/re_renderer/examples/multiview.rs index 0c48dd2b456c..82c7fd405a69 100644 --- a/crates/re_renderer/examples/multiview.rs +++ b/crates/re_renderer/examples/multiview.rs @@ -101,7 +101,7 @@ fn build_lines(re_ctx: &mut RenderContext, seconds_since_startup: f32) -> LineDr // Calculate some points that look nice for an animated line. let lorenz_points = lorenz_points(seconds_since_startup); - let mut builder = LineStripSeriesBuilder::<()>::default(); + let mut builder = LineStripSeriesBuilder::<()>::new(re_ctx); { let mut batch = builder.batch("lines without transform"); diff --git a/crates/re_renderer/shader/depth_cloud.wgsl b/crates/re_renderer/shader/depth_cloud.wgsl index 912dfe38d411..62d6e926669c 100644 --- a/crates/re_renderer/shader/depth_cloud.wgsl +++ b/crates/re_renderer/shader/depth_cloud.wgsl @@ -92,7 +92,8 @@ fn vs_main(@builtin(vertex_index) vertex_idx: u32) -> VertexOut { let point_data = compute_point_data(quad_idx); // Span quad - let quad = sphere_quad_span(vertex_idx, point_data.pos_in_world, point_data.unresolved_radius); + // TODO(andreas): Implement outline-mask size boost for depth cloud as well. + let quad = sphere_quad_span(vertex_idx, point_data.pos_in_world, point_data.unresolved_radius, 0.0); var out: VertexOut; out.pos_in_clip = frame.projection_from_world * Vec4(quad.pos_in_world, 1.0); diff --git a/crates/re_renderer/shader/lines.wgsl b/crates/re_renderer/shader/lines.wgsl index b791715e913d..e214d302f558 100644 --- a/crates/re_renderer/shader/lines.wgsl +++ b/crates/re_renderer/shader/lines.wgsl @@ -11,6 +11,12 @@ var line_strip_texture: texture_2d; @group(1) @binding(1) var position_data_texture: texture_2d; +struct DrawDataUniformBuffer { + size_boost_in_points: f32, +}; +@group(1) @binding(2) +var draw_data: DrawDataUniformBuffer; + struct BatchUniformBuffer { world_from_obj: Mat4, outline_mask_ids: UVec2, @@ -159,11 +165,6 @@ fn vs_main(@builtin(vertex_index) vertex_idx: u32) -> VertexOut { // Data valid for the entire strip that this vertex belongs to. let strip_data = read_strip_data(pos_data_current.strip_index); - // Resolve radius. - // (slight inaccuracy: End caps are going to adjust their center_position) - let camera_ray = camera_ray_to_world_pos(center_position); - let strip_radius = unresolved_size_to_world(strip_data.unresolved_radius, length(camera_ray.origin - center_position), frame.auto_size_lines); - // Active flags are all flags that we react to at the current vertex. // I.e. cap flags are only active in the respective cap triangle. var currently_active_flags = strip_data.flags & (~(CAP_START_TRIANGLE | CAP_END_TRIANGLE | CAP_START_ROUND | CAP_END_ROUND)); @@ -189,6 +190,20 @@ fn vs_main(@builtin(vertex_index) vertex_idx: u32) -> VertexOut { quad_dir = normalize(pos_data_quad_end.pos - pos_data_quad_begin.pos); } + // Resolve radius. + // (slight inaccuracy: End caps are going to adjust their center_position) + let camera_ray = camera_ray_to_world_pos(center_position); + let camera_distance = distance(camera_ray.origin, center_position); + var strip_radius = unresolved_size_to_world(strip_data.unresolved_radius, camera_distance, frame.auto_size_lines); + if draw_data.size_boost_in_points > 0.0 { + let size_boost = world_size_from_point_size(draw_data.size_boost_in_points, camera_distance); + strip_radius += size_boost; + // Push out positions as well along the quad dir. + // This is especially important if there's no miters on a line-strip (TODO(#829)), + // as this would enhance gaps between lines otherwise. + center_position += quad_dir * (size_boost * select(-1.0, 1.0, is_at_quad_end)); + } + var active_radius = strip_radius; // If this is a triangle cap, we blow up our ("virtual") quad by twice the size. if has_any_flag(currently_active_flags, CAP_START_TRIANGLE | CAP_END_TRIANGLE) { diff --git a/crates/re_renderer/shader/point_cloud.wgsl b/crates/re_renderer/shader/point_cloud.wgsl index e3db9bf4ce18..86b12cfd2214 100644 --- a/crates/re_renderer/shader/point_cloud.wgsl +++ b/crates/re_renderer/shader/point_cloud.wgsl @@ -10,6 +10,12 @@ var position_data_texture: texture_2d; @group(1) @binding(1) var color_texture: texture_2d; +struct DrawDataUniformBuffer { + size_boost_in_points: f32, +}; +@group(1) @binding(2) +var draw_data: DrawDataUniformBuffer; + struct BatchUniformBuffer { world_from_obj: Mat4, flags: u32, @@ -63,7 +69,7 @@ fn vs_main(@builtin(vertex_index) vertex_idx: u32) -> VertexOut { let point_data = read_data(quad_idx); // Span quad - let quad = sphere_quad_span(vertex_idx, point_data.pos, point_data.unresolved_radius); + let quad = sphere_quad_span(vertex_idx, point_data.pos, point_data.unresolved_radius, draw_data.size_boost_in_points); // Output, transform to projection space and done. var out: VertexOut; diff --git a/crates/re_renderer/shader/utils/size.wgsl b/crates/re_renderer/shader/utils/size.wgsl index aae7cc4298b5..afd1cf6300b3 100644 --- a/crates/re_renderer/shader/utils/size.wgsl +++ b/crates/re_renderer/shader/utils/size.wgsl @@ -2,6 +2,10 @@ #import +fn world_size_from_point_size(size_in_points: f32, camera_distance: f32) -> f32 { + let pixel_size = frame.pixels_from_point * size_in_points; + return approx_pixel_world_size_at(camera_distance) * pixel_size; +} fn unresolved_size_to_world(_unresolved_size: f32, camera_distance: f32, auto_size: f32) -> f32 { // Resolve auto size. @@ -23,6 +27,5 @@ fn unresolved_size_to_world(_unresolved_size: f32, camera_distance: f32, auto_si } // Negative size indicates size in points. - let pixel_size = frame.pixels_from_point * (-unresolved_size); - return approx_pixel_world_size_at(camera_distance) * pixel_size; + return world_size_from_point_size(-unresolved_size, camera_distance); } diff --git a/crates/re_renderer/shader/utils/sphere_quad.wgsl b/crates/re_renderer/shader/utils/sphere_quad.wgsl index 56df0e5aa134..25c78d320db3 100644 --- a/crates/re_renderer/shader/utils/sphere_quad.wgsl +++ b/crates/re_renderer/shader/utils/sphere_quad.wgsl @@ -68,11 +68,12 @@ struct SphereQuadData { /// Span a quad onto which perspective correct spheres can be drawn. /// /// Spanning is done in perspective or orthographically depending of the state of the global cam. -fn sphere_quad_span(vertex_idx: u32, point_pos: Vec3, point_unresolved_radius: f32) -> SphereQuadData { +fn sphere_quad_span(vertex_idx: u32, point_pos: Vec3, point_unresolved_radius: f32, size_boost_in_points: f32) -> SphereQuadData { // Resolve radius to a world size. We need the camera distance for this, which is useful later on. let to_camera = frame.camera_position - point_pos; let camera_distance = length(to_camera); - let radius = unresolved_size_to_world(point_unresolved_radius, camera_distance, frame.auto_size_points); + let radius = unresolved_size_to_world(point_unresolved_radius, camera_distance, frame.auto_size_points) + + world_size_from_point_size(size_boost_in_points, camera_distance); // Basic properties of the vertex we're at. let local_idx = vertex_idx % 6u; diff --git a/crates/re_renderer/src/line_strip_builder.rs b/crates/re_renderer/src/line_strip_builder.rs index 9e65a6312573..3da02a0e122e 100644 --- a/crates/re_renderer/src/line_strip_builder.rs +++ b/crates/re_renderer/src/line_strip_builder.rs @@ -5,7 +5,7 @@ use crate::{ LineBatchInfo, LineDrawData, LineStripFlags, LineStripInfo, LineVertex, OutlineMaskPreference, }, - Color32, DebugLabel, Size, + Color32, DebugLabel, RenderContext, Size, }; /// Builder for a vector of line strips, making it easy to create [`crate::renderer::LineDrawData`]. @@ -14,7 +14,6 @@ use crate::{ /// of writing to a GPU readable memory location. /// This will require some ahead of time size limit, but should be feasible. /// But before that we first need to sort out cpu->gpu transfers better by providing staging buffers. -#[derive(Default)] pub struct LineStripSeriesBuilder { pub vertices: Vec, @@ -23,12 +22,36 @@ pub struct LineStripSeriesBuilder { pub strip_user_data: Vec, pub batches: Vec, + + pub(crate) size_boost_in_points_for_outlines: f32, } impl LineStripSeriesBuilder where PerStripUserData: Default + Copy, { + // TODO(andreas): ctx not yet needed since we don't write to GPU yet, but soon needed. + pub fn new(_ctx: &RenderContext) -> Self { + const RESERVE_SIZE: usize = 512; + + Self { + vertices: Vec::with_capacity(RESERVE_SIZE * 2), + strips: Vec::with_capacity(RESERVE_SIZE), + strip_user_data: Vec::with_capacity(RESERVE_SIZE), + batches: Vec::with_capacity(16), + size_boost_in_points_for_outlines: 0.0, + } + } + + /// Boosts the size of the points by the given amount of ui-points for the purpose of drawing outlines. + pub fn size_boost_in_points_for_outlines( + mut self, + size_boost_in_points_for_outlines: f32, + ) -> Self { + self.size_boost_in_points_for_outlines = size_boost_in_points_for_outlines; + self + } + /// Start of a new batch. pub fn batch( &mut self, @@ -65,7 +88,14 @@ where /// Finalizes the builder and returns a line draw data with all the lines added so far. pub fn to_draw_data(&self, ctx: &mut crate::context::RenderContext) -> LineDrawData { - LineDrawData::new(ctx, &self.vertices, &self.strips, &self.batches).unwrap() + LineDrawData::new( + ctx, + &self.vertices, + &self.strips, + &self.batches, + self.size_boost_in_points_for_outlines, + ) + .unwrap() } /// Iterates over all line strips batches together with their strips and their respective vertices. diff --git a/crates/re_renderer/src/point_cloud_builder.rs b/crates/re_renderer/src/point_cloud_builder.rs index 27ac2de8b8de..26f3e8387bad 100644 --- a/crates/re_renderer/src/point_cloud_builder.rs +++ b/crates/re_renderer/src/point_cloud_builder.rs @@ -16,13 +16,15 @@ pub struct PointCloudBuilder { pub user_data: Vec, pub(crate) batches: Vec, + + pub(crate) size_boost_in_points_for_outlines: f32, } impl PointCloudBuilder where PerPointUserData: Default + Copy, { - pub fn new(ctx: &mut RenderContext) -> Self { + pub fn new(ctx: &RenderContext) -> Self { const RESERVE_SIZE: usize = 512; // TODO(andreas): Be more resourceful about the size allocated here. Typically we know in advance! @@ -37,9 +39,19 @@ where color_buffer, user_data: Vec::with_capacity(RESERVE_SIZE), batches: Vec::with_capacity(16), + size_boost_in_points_for_outlines: 0.0, } } + /// Boosts the size of the points by the given amount of ui-points for the purpose of drawing outlines. + pub fn size_boost_in_points_for_outlines( + mut self, + size_boost_in_points_for_outlines: f32, + ) -> Self { + self.size_boost_in_points_for_outlines = size_boost_in_points_for_outlines; + self + } + /// Start of a new batch. #[inline] pub fn batch( diff --git a/crates/re_renderer/src/renderer/lines.rs b/crates/re_renderer/src/renderer/lines.rs index 0767bd30bda4..0915434bdbe2 100644 --- a/crates/re_renderer/src/renderer/lines.rs +++ b/crates/re_renderer/src/renderer/lines.rs @@ -160,6 +160,14 @@ pub mod gpu_data { } static_assertions::assert_eq_size!(LineStripInfo, [u32; 2]); + /// Uniform buffer that changes once per draw data rendering. + #[repr(C, align(256))] + #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] + pub struct DrawDataUniformBuffer { + pub size_boost_in_points: wgpu_buffer_types::F32RowPadded, + pub end_padding: [wgpu_buffer_types::PaddingRow; 16 - 1], + } + /// Uniform buffer that changes for every batch of line strips. #[repr(C, align(256))] #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] @@ -184,6 +192,7 @@ struct LineStripBatch { #[derive(Clone)] pub struct LineDrawData { bind_group_all_lines: Option, + bind_group_all_lines_outline_mask: Option, batches: Vec, } @@ -312,9 +321,11 @@ impl LineDrawData { /// If no batches are passed, all lines are assumed to be in a single batch with identity transform. pub fn new( ctx: &mut RenderContext, + // TODO(andreas): Take LineBuilder directly vertices: &[gpu_data::LineVertex], strips: &[LineStripInfo], batches: &[LineBatchInfo], + size_boost_in_points_for_outlines: f32, ) -> Result { let mut renderers = ctx.renderers.write(); let line_renderer = renderers.get_or_create::<_, LineRenderer>( @@ -327,6 +338,7 @@ impl LineDrawData { if strips.is_empty() { return Ok(LineDrawData { bind_group_all_lines: None, + bind_group_all_lines_outline_mask: None, batches: Vec::new(), }); } @@ -495,14 +507,43 @@ impl LineDrawData { }, ); + let draw_data_uniform_buffer_bindings = create_and_fill_uniform_buffer_batch( + ctx, + "LineDrawData::DrawDataUniformBuffer".into(), + [ + gpu_data::DrawDataUniformBuffer { + size_boost_in_points: 0.0.into(), + end_padding: Default::default(), + }, + gpu_data::DrawDataUniformBuffer { + size_boost_in_points: size_boost_in_points_for_outlines.into(), + end_padding: Default::default(), + }, + ] + .into_iter(), + ); let bind_group_all_lines = ctx.gpu_resources.bind_groups.alloc( &ctx.device, &ctx.gpu_resources, &BindGroupDesc { - label: "line draw data".into(), + label: "LineDrawData::bind_group_all_lines".into(), + entries: smallvec![ + BindGroupEntry::DefaultTextureView(position_data_texture.handle), + BindGroupEntry::DefaultTextureView(line_strip_texture.handle), + draw_data_uniform_buffer_bindings[0].clone(), + ], + layout: line_renderer.bind_group_layout_all_lines, + }, + ); + let bind_group_all_lines_outline_mask = ctx.gpu_resources.bind_groups.alloc( + &ctx.device, + &ctx.gpu_resources, + &BindGroupDesc { + label: "LineDrawData::bind_group_all_lines_outline_mask".into(), entries: smallvec![ BindGroupEntry::DefaultTextureView(position_data_texture.handle), BindGroupEntry::DefaultTextureView(line_strip_texture.handle), + draw_data_uniform_buffer_bindings[1].clone(), ], layout: line_renderer.bind_group_layout_all_lines, }, @@ -597,6 +638,7 @@ impl LineDrawData { Ok(LineDrawData { bind_group_all_lines: Some(bind_group_all_lines), + bind_group_all_lines_outline_mask: Some(bind_group_all_lines_outline_mask), batches: batches_internal, }) } @@ -679,6 +721,18 @@ impl Renderer for LineRenderer { }, count: None, }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: NonZeroU64::new(std::mem::size_of::< + gpu_data::DrawDataUniformBuffer, + >() as _), + }, + count: None, + }, ], }, ); @@ -789,15 +843,18 @@ impl Renderer for LineRenderer { pass: &mut wgpu::RenderPass<'a>, draw_data: &'a Self::RendererDrawData, ) -> anyhow::Result<()> { - let Some(bind_group_all_lines) = &draw_data.bind_group_all_lines else { + let (pipeline_handle, bind_group_all_lines) = match phase { + DrawPhase::OutlineMask => ( + self.render_pipeline_outline_mask, + &draw_data.bind_group_all_lines_outline_mask, + ), + DrawPhase::Opaque => (self.render_pipeline_color, &draw_data.bind_group_all_lines), + _ => unreachable!("We were called on a phase we weren't subscribed to: {phase:?}"), + }; + let Some(bind_group_all_lines) = bind_group_all_lines else { return Ok(()); // No lines submitted. }; - let pipeline_handle = match phase { - DrawPhase::OutlineMask => self.render_pipeline_outline_mask, - DrawPhase::Opaque => self.render_pipeline_color, - _ => unreachable!("We were called on a phase we weren't subscribed to: {phase:?}"), - }; let pipeline = pools.render_pipelines.get_resource(pipeline_handle)?; pass.set_pipeline(pipeline); diff --git a/crates/re_renderer/src/renderer/point_cloud.rs b/crates/re_renderer/src/renderer/point_cloud.rs index 369d87b07587..ec12cb03c0ec 100644 --- a/crates/re_renderer/src/renderer/point_cloud.rs +++ b/crates/re_renderer/src/renderer/point_cloud.rs @@ -68,6 +68,14 @@ mod gpu_data { } static_assertions::assert_eq_size!(PositionData, glam::Vec4); + /// Uniform buffer that changes once per draw data rendering. + #[repr(C, align(256))] + #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] + pub struct DrawDataUniformBuffer { + pub size_boost_in_points: wgpu_buffer_types::F32RowPadded, + pub end_padding: [wgpu_buffer_types::PaddingRow; 16 - 1], + } + /// Uniform buffer that changes for every batch of points. #[repr(C, align(256))] #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] @@ -93,6 +101,7 @@ struct PointCloudBatch { #[derive(Clone)] pub struct PointCloudDrawData { bind_group_all_points: Option, + bind_group_all_points_outline_mask: Option, batches: Vec, } @@ -184,6 +193,7 @@ impl PointCloudDrawData { if vertices.is_empty() { return Ok(PointCloudDrawData { bind_group_all_points: None, + bind_group_all_points_outline_mask: None, batches: Vec::new(), }); } @@ -315,14 +325,44 @@ impl PointCloudDrawData { size, ); + let draw_data_uniform_buffer_bindings = create_and_fill_uniform_buffer_batch( + ctx, + "PointCloudDrawData::DrawDataUniformBuffer".into(), + [ + gpu_data::DrawDataUniformBuffer { + size_boost_in_points: 0.0.into(), + end_padding: Default::default(), + }, + gpu_data::DrawDataUniformBuffer { + size_boost_in_points: builder.size_boost_in_points_for_outlines.into(), + end_padding: Default::default(), + }, + ] + .into_iter(), + ); + let bind_group_all_points = ctx.gpu_resources.bind_groups.alloc( &ctx.device, &ctx.gpu_resources, &BindGroupDesc { - label: "line drawdata".into(), + label: "PointCloudDrawData::bind_group_all_points".into(), entries: smallvec![ BindGroupEntry::DefaultTextureView(position_data_texture.handle), BindGroupEntry::DefaultTextureView(color_texture.handle), + draw_data_uniform_buffer_bindings[0].clone(), + ], + layout: point_renderer.bind_group_layout_all_points, + }, + ); + let bind_group_all_points_outline_mask = ctx.gpu_resources.bind_groups.alloc( + &ctx.device, + &ctx.gpu_resources, + &BindGroupDesc { + label: "PointCloudDrawData::bind_group_all_points_outline_mask".into(), + entries: smallvec![ + BindGroupEntry::DefaultTextureView(position_data_texture.handle), + BindGroupEntry::DefaultTextureView(color_texture.handle), + draw_data_uniform_buffer_bindings[1].clone(), ], layout: point_renderer.bind_group_layout_all_points, }, @@ -413,6 +453,7 @@ impl PointCloudDrawData { Ok(PointCloudDrawData { bind_group_all_points: Some(bind_group_all_points), + bind_group_all_points_outline_mask: Some(bind_group_all_points_outline_mask), batches: batches_internal, }) } @@ -494,6 +535,18 @@ impl Renderer for PointCloudRenderer { }, count: None, }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: NonZeroU64::new(std::mem::size_of::< + gpu_data::DrawDataUniformBuffer, + >() as _), + }, + count: None, + }, ], }, ); @@ -599,15 +652,18 @@ impl Renderer for PointCloudRenderer { pass: &mut wgpu::RenderPass<'a>, draw_data: &'a Self::RendererDrawData, ) -> anyhow::Result<()> { - let Some(bind_group_all_points) = &draw_data.bind_group_all_points else { + let (pipeline_handle, bind_group_all_points) = match phase { + DrawPhase::OutlineMask => ( + self.render_pipeline_outline_mask, + &draw_data.bind_group_all_points_outline_mask, + ), + DrawPhase::Opaque => (self.render_pipeline_color, &draw_data.bind_group_all_points), + _ => unreachable!("We were called on a phase we weren't subscribed to: {phase:?}"), + }; + let Some(bind_group_all_points) = bind_group_all_points else { return Ok(()); // No points submitted. }; - let pipeline_handle = match phase { - DrawPhase::OutlineMask => self.render_pipeline_outline_mask, - DrawPhase::Opaque => self.render_pipeline_color, - _ => unreachable!("We were called on a phase we weren't subscribed to: {phase:?}"), - }; let pipeline = pools.render_pipelines.get_resource(pipeline_handle)?; pass.set_pipeline(pipeline); diff --git a/crates/re_viewer/src/ui/view_spatial/scene/picking.rs b/crates/re_viewer/src/ui/view_spatial/scene/picking.rs index 2f9204c2fe1a..29133aa75fa0 100644 --- a/crates/re_viewer/src/ui/view_spatial/scene/picking.rs +++ b/crates/re_viewer/src/ui/view_spatial/scene/picking.rs @@ -164,7 +164,6 @@ pub fn picking( textured_rectangles, textured_rectangles_ids, line_strips, - line_strips_outline_only: _, points, meshes, depth_clouds: _, // no picking for depth clouds yet diff --git a/crates/re_viewer/src/ui/view_spatial/scene/primitives.rs b/crates/re_viewer/src/ui/view_spatial/scene/primitives.rs index 7c66391f2d1b..f65fc234f474 100644 --- a/crates/re_viewer/src/ui/view_spatial/scene/primitives.rs +++ b/crates/re_viewer/src/ui/view_spatial/scene/primitives.rs @@ -23,7 +23,6 @@ pub struct SceneSpatialPrimitives { pub textured_rectangles: Vec, pub line_strips: LineStripSeriesBuilder, - pub line_strips_outline_only: LineStripSeriesBuilder<()>, pub points: PointCloudBuilder, pub meshes: Vec, @@ -36,15 +35,19 @@ const AXIS_COLOR_X: Color32 = Color32::from_rgb(255, 25, 25); const AXIS_COLOR_Y: Color32 = Color32::from_rgb(0, 240, 0); const AXIS_COLOR_Z: Color32 = Color32::from_rgb(80, 80, 255); +const SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES: f32 = 1.5; +const SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES: f32 = 2.5; + impl SceneSpatialPrimitives { pub fn new(re_ctx: &mut re_renderer::RenderContext) -> Self { Self { bounding_box: macaw::BoundingBox::nothing(), textured_rectangles_ids: Default::default(), textured_rectangles: Default::default(), - line_strips: Default::default(), - line_strips_outline_only: Default::default(), - points: PointCloudBuilder::new(re_ctx), + line_strips: LineStripSeriesBuilder::new(re_ctx) + .size_boost_in_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES), + points: PointCloudBuilder::new(re_ctx) + .size_boost_in_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES), meshes: Default::default(), depth_clouds: Default::default(), any_outlines: false, @@ -63,7 +66,6 @@ impl SceneSpatialPrimitives { textured_rectangles, textured_rectangles_ids: _, line_strips, - line_strips_outline_only: _, points, meshes, depth_clouds, @@ -85,7 +87,6 @@ impl SceneSpatialPrimitives { textured_rectangles_ids: _, textured_rectangles, line_strips, - line_strips_outline_only: _, points, meshes, depth_clouds: _, // no bbox for depth clouds diff --git a/crates/re_viewer/src/ui/view_spatial/ui.rs b/crates/re_viewer/src/ui/view_spatial/ui.rs index 4cf7ac86cd9b..831454f37a75 100644 --- a/crates/re_viewer/src/ui/view_spatial/ui.rs +++ b/crates/re_viewer/src/ui/view_spatial/ui.rs @@ -636,13 +636,14 @@ pub fn create_labels( } pub fn outline_config(gui_ctx: &egui::Context) -> OutlineConfig { + // Take the exact same colors we have in the ui! let selection_outline_color = re_renderer::Rgba::from(gui_ctx.style().visuals.selection.bg_fill); - let selection_outline_color = selection_outline_color * 0.75; // Three-quarter-transparent - let hover_outline_color = (selection_outline_color * 2.0).additive(); + let hover_outline_color = + re_renderer::Rgba::from(gui_ctx.style().visuals.widgets.hovered.bg_fill); OutlineConfig { - outline_radius_pixel: (gui_ctx.pixels_per_point() * 2.5).at_least(1.0), + outline_radius_pixel: (gui_ctx.pixels_per_point() * 1.5).at_least(0.5), color_layer_a: selection_outline_color, color_layer_b: hover_outline_color, }