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 2 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
69 changes: 1 addition & 68 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_preview_ui;
use re_viewer_context::{
gpu_bridge, SpaceViewClass, SpaceViewClassName, SpaceViewClassRegistryError, SpaceViewId,
SpaceViewState, SpaceViewSystemExecutionError, TensorStatsCache, ViewContextCollection,
Expand Down Expand Up @@ -421,74 +422,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
64 changes: 42 additions & 22 deletions crates/re_viewer/src/ui/selection_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use re_data_store::{ColorMapper, Colormap, EditableAutoValue, EntityPath, Entity
use re_data_ui::{image_meaning_for_entity, item_ui, DataUi};
use re_log_types::TimeType;
use re_types::{components::Transform3D, tensor_data::TensorDataMeaning};
use re_viewer_context::{Item, SpaceViewId, UiVerbosity, ViewerContext};
use re_viewer_context::{
gpu_bridge::colormap_preview_ui, Item, SpaceViewId, UiVerbosity, ViewerContext,
};
use re_viewport::{Viewport, ViewportBlueprint};

use super::selection_history_ui::SelectionHistoryUi;
Expand Down Expand Up @@ -409,32 +411,50 @@ 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 current = 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")
egui::ComboBox::from_id_source("color map select")
.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));
egui::Grid::new("colormap_selector")
.num_columns(2)
.show(ui, |ui| {
for option in re_renderer::Colormap::ALL {
let mut value = current;
if ui
.selectable_value(&mut value, option, option.to_string())
.changed()
{
let value = match value {
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(value));
}
colormap_preview_ui(ctx.render_ctx, ui, option);
ui.end_row();
}
});
Wumpf marked this conversation as resolved.
Show resolved Hide resolved
});

ui.end_row();
Expand Down Expand Up @@ -518,7 +538,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
70 changes: 70 additions & 0 deletions crates/re_viewer_context/src/gpu_bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,73 @@ pub fn render_image(

Ok(())
}

fn paint_colormap_gradient(
render_ctx: &mut re_renderer::RenderContext,
colormap: re_renderer::Colormap,
painter: &egui::Painter,
rect: egui::Rect,
) -> anyhow::Result<()> {
re_tracing::profile_function!();

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,
painter,
rect,
colormapped_texture,
egui::TextureOptions::LINEAR,
&debug_name,
)
}

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

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

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

response
}