Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix colormap picker preview & show it for depth point clouds as well #3373

Merged
merged 6 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 2 additions & 83 deletions crates/re_space_view_tensor/src/space_view_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use re_types::{
datatypes::{TensorData, TensorDimension},
tensor_data::{DecodedTensor, TensorDataMeaning},
};
use re_viewer_context::gpu_bridge::colormap_dropdown_button_ui;
use re_viewer_context::{
gpu_bridge, SpaceViewClass, SpaceViewClassName, SpaceViewClassRegistryError, SpaceViewId,
SpaceViewState, SpaceViewSystemExecutionError, TensorStatsCache, ViewContextCollection,
Expand Down Expand Up @@ -396,21 +397,7 @@ impl ColorMapping {
let ColorMapping { map, gamma } = self;

re_ui.grid_left_hand_label(ui, "Color map");
egui::ComboBox::from_id_source("color map select")
.selected_text(map.to_string())
.show_ui(ui, |ui| {
ui.style_mut().wrap = Some(false);

egui::Grid::new("colormap_selector")
.num_columns(2)
.show(ui, |ui| {
for option in Colormap::ALL {
ui.selectable_value(map, option, option.to_string());
colormap_preview_ui(render_ctx, ui, option);
ui.end_row();
}
});
});
colormap_dropdown_button_ui(render_ctx, ui, map);
ui.end_row();

re_ui.grid_left_hand_label(ui, "Brightness");
Expand All @@ -421,74 +408,6 @@ impl ColorMapping {
}
}

/// Show the given colormap as a horizontal bar.
fn colormap_preview_ui(
render_ctx: &mut re_renderer::RenderContext,
ui: &mut egui::Ui,
colormap: Colormap,
) -> egui::Response {
re_tracing::profile_function!();

let desired_size = egui::vec2(128.0, 16.0);
let (rect, response) = ui.allocate_exact_size(desired_size, egui::Sense::hover());

if ui.is_rect_visible(rect) {
if let Err(err) = paint_colormap_gradient(render_ctx, colormap, ui, rect) {
re_log::error_once!("Failed to paint colormap preview: {err}");
}
}

response
}

fn paint_colormap_gradient(
render_ctx: &mut re_renderer::RenderContext,
colormap: Colormap,
ui: &mut egui::Ui,
rect: egui::Rect,
) -> anyhow::Result<()> {
let horizontal_gradient_id = egui::util::hash("horizontal_gradient");
let horizontal_gradient =
gpu_bridge::get_or_create_texture(render_ctx, horizontal_gradient_id, || {
let width = 256;
let height = 1;
let data: Vec<u8> = (0..width)
.flat_map(|x| {
let t = x as f32 / (width as f32 - 1.0);
half::f16::from_f32(t).to_le_bytes()
})
.collect();

re_renderer::resource_managers::Texture2DCreationDesc {
label: "horizontal_gradient".into(),
data: data.into(),
format: wgpu::TextureFormat::R16Float,
width,
height,
}
})
.map_err(|err| anyhow::anyhow!("Failed to create horizontal gradient texture: {err}"))?;

let colormapped_texture = re_renderer::renderer::ColormappedTexture {
texture: horizontal_gradient,
range: [0.0, 1.0],
decode_srgb: false,
multiply_rgb_with_alpha: false,
gamma: 1.0,
color_mapper: Some(re_renderer::renderer::ColorMapper::Function(colormap)),
};

let debug_name = format!("colormap_{colormap}");
gpu_bridge::render_image(
render_ctx,
ui.painter(),
rect,
colormapped_texture,
egui::TextureOptions::LINEAR,
&debug_name,
)
}

// ----------------------------------------------------------------------------

/// Should we scale the rendered texture, and if so, how?
Expand Down
55 changes: 28 additions & 27 deletions crates/re_viewer/src/ui/selection_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use re_types::{
components::{PinholeProjection, Transform3D},
tensor_data::TensorDataMeaning,
};
use re_viewer_context::{Item, SpaceViewId, UiVerbosity, ViewerContext};
use re_viewer_context::{
gpu_bridge::colormap_dropdown_button_ui, Item, SpaceViewId, UiVerbosity, ViewerContext,
};
use re_viewport::{Viewport, ViewportBlueprint};

use super::selection_history_ui::SelectionHistoryUi;
Expand Down Expand Up @@ -411,33 +413,32 @@ fn entity_props_ui(
});
}

fn colormap_props_ui(ui: &mut egui::Ui, entity_props: &mut EntityProperties) {
let current = *entity_props.color_mapper.get();
fn colormap_props_ui(
ctx: &mut ViewerContext<'_>,
ui: &mut egui::Ui,
entity_props: &mut EntityProperties,
) {
let mut re_renderer_colormap = match *entity_props.color_mapper.get() {
ColorMapper::Colormap(Colormap::Grayscale) => re_renderer::Colormap::Grayscale,
ColorMapper::Colormap(Colormap::Turbo) => re_renderer::Colormap::Turbo,
ColorMapper::Colormap(Colormap::Viridis) => re_renderer::Colormap::Viridis,
ColorMapper::Colormap(Colormap::Plasma) => re_renderer::Colormap::Plasma,
ColorMapper::Colormap(Colormap::Magma) => re_renderer::Colormap::Magma,
ColorMapper::Colormap(Colormap::Inferno) => re_renderer::Colormap::Inferno,
};

ui.label("Color map");
egui::ComboBox::from_id_source("color_mapper")
.selected_text(current.to_string())
.show_ui(ui, |ui| {
ui.style_mut().wrap = Some(false);
ui.set_min_width(64.0);

// TODO(cmc): that is not ideal but I don't want to import yet another proc-macro...
let mut add_label = |proposed| {
if ui
.selectable_label(current == proposed, proposed.to_string())
.clicked()
{
entity_props.color_mapper = EditableAutoValue::UserEdited(proposed);
}
};

add_label(ColorMapper::Colormap(Colormap::Grayscale));
add_label(ColorMapper::Colormap(Colormap::Turbo));
add_label(ColorMapper::Colormap(Colormap::Viridis));
add_label(ColorMapper::Colormap(Colormap::Plasma));
add_label(ColorMapper::Colormap(Colormap::Magma));
add_label(ColorMapper::Colormap(Colormap::Inferno));
});
colormap_dropdown_button_ui(ctx.render_ctx, ui, &mut re_renderer_colormap);

let new_colormap = match re_renderer_colormap {
re_renderer::Colormap::Grayscale => Colormap::Grayscale,
re_renderer::Colormap::Turbo => Colormap::Turbo,
re_renderer::Colormap::Viridis => Colormap::Viridis,
re_renderer::Colormap::Plasma => Colormap::Plasma,
re_renderer::Colormap::Magma => Colormap::Magma,
re_renderer::Colormap::Inferno => Colormap::Inferno,
};
entity_props.color_mapper = EditableAutoValue::UserEdited(ColorMapper::Colormap(new_colormap));

ui.end_row();
}
Expand Down Expand Up @@ -520,7 +521,7 @@ fn depth_props_ui(

// TODO(cmc): This should apply to the depth map entity as a whole, but for that we
// need to get the current hardcoded colormapping out of the image cache first.
colormap_props_ui(ui, entity_props);
colormap_props_ui(ctx, ui, entity_props);
}

Some(())
Expand Down
83 changes: 83 additions & 0 deletions crates/re_viewer_context/src/gpu_bridge/colormap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::gpu_bridge::{get_or_create_texture, render_image};

/// Show the given colormap as a horizontal bar.
fn colormap_preview_ui(
render_ctx: &mut re_renderer::RenderContext,
ui: &mut egui::Ui,
colormap: re_renderer::Colormap,
) -> anyhow::Result<egui::Response> {
re_tracing::profile_function!();

let desired_size = egui::vec2(128.0, 16.0);
let (rect, response) = ui.allocate_at_least(desired_size, egui::Sense::hover());

if !ui.is_rect_visible(rect) {
return Ok(response);
}

let horizontal_gradient_id = egui::util::hash("horizontal_gradient");
let horizontal_gradient = get_or_create_texture(render_ctx, horizontal_gradient_id, || {
let width = 256;
let height = 1;
let data: Vec<u8> = (0..width)
.flat_map(|x| {
let t = x as f32 / (width as f32 - 1.0);
half::f16::from_f32(t).to_le_bytes()
})
.collect();

re_renderer::resource_managers::Texture2DCreationDesc {
label: "horizontal_gradient".into(),
data: data.into(),
format: wgpu::TextureFormat::R16Float,
width,
height,
}
})
.map_err(|err| anyhow::anyhow!("Failed to create horizontal gradient texture: {err}"))?;

let colormapped_texture = re_renderer::renderer::ColormappedTexture {
texture: horizontal_gradient,
range: [0.0, 1.0],
decode_srgb: false,
multiply_rgb_with_alpha: false,
gamma: 1.0,
color_mapper: Some(re_renderer::renderer::ColorMapper::Function(colormap)),
};

let debug_name = format!("colormap_{colormap}");
render_image(
render_ctx,
ui.painter(),
rect,
colormapped_texture,
egui::TextureOptions::LINEAR,
&debug_name,
)?;

Ok(response)
}

pub fn colormap_dropdown_button_ui(
render_ctx: &mut re_renderer::RenderContext,
ui: &mut egui::Ui,
map: &mut re_renderer::Colormap,
) {
egui::ComboBox::from_id_source("color map select")
.selected_text(map.to_string())
.show_ui(ui, |ui| {
ui.style_mut().wrap = Some(false);

egui::Grid::new("colormap_selector")
.num_columns(2)
.show(ui, |ui| {
for option in re_renderer::Colormap::ALL {
ui.selectable_value(map, option, option.to_string());
if let Err(err) = colormap_preview_ui(render_ctx, ui, option) {
re_log::error_once!("Failed to paint colormap preview: {err}");
}
ui.end_row();
}
});
});
}
2 changes: 2 additions & 0 deletions crates/re_viewer_context/src/gpu_bridge/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Bridge to `re_renderer`

mod colormap;
mod re_renderer_callback;
mod tensor_to_gpu;

pub use colormap::colormap_dropdown_button_ui;
pub use re_renderer_callback::new_renderer_callback;
pub use tensor_to_gpu::{
class_id_tensor_to_gpu, color_tensor_to_gpu, depth_tensor_to_gpu, tensor_to_gpu,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl egui_wgpu::CallbackTrait for ReRendererCallback {
return;
};

let screen_position = (info.clip_rect.min.to_vec2() * info.pixels_per_point).round();
let screen_position = (info.viewport.min.to_vec2() * info.pixels_per_point).round();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the actual bugfix!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, nice one!

let screen_position = glam::vec2(screen_position.x, screen_position.y);

view_builder.composite(ctx, render_pass, screen_position);
Expand Down