diff --git a/crates/re_renderer/examples/depth_cloud.rs b/crates/re_renderer/examples/depth_cloud.rs index 8e2b6a0fa41d..0a1f1391f677 100644 --- a/crates/re_renderer/examples/depth_cloud.rs +++ b/crates/re_renderer/examples/depth_cloud.rs @@ -396,39 +396,6 @@ fn spiral(dimensions: glam::UVec2) -> impl Iterator { }) } -// Copied from re_viewer, this will be removed in an upcoming PR that handles colormapping. -// -// Copyright 2019 Google LLC. -// SPDX-License-Identifier: Apache-2.0 -// Authors: -// Colormap Design: Anton Mikhailov (mikhailov@google.com) -// GLSL Approximation: Ruofei Du (ruofei@google.com)/ -// -// TODO(cmc): remove in GPU color maps PR. -#[allow(clippy::excessive_precision)] -fn turbo_color_map(x: f32) -> [u8; 4] { - use glam::{Vec2, Vec4}; - - const RED_VEC4: Vec4 = Vec4::new(0.13572138, 4.61539260, -42.66032258, 132.13108234); - const GREEN_VEC4: Vec4 = Vec4::new(0.09140261, 2.19418839, 4.84296658, -14.18503333); - const BLUE_VEC4: Vec4 = Vec4::new(0.10667330, 12.64194608, -60.58204836, 110.36276771); - const RED_VEC2: Vec2 = Vec2::new(-152.94239396, 59.28637943); - const GREEN_VEC2: Vec2 = Vec2::new(4.27729857, 2.82956604); - const BLURE_VEC2: Vec2 = Vec2::new(-89.90310912, 27.34824973); - - let v4 = glam::vec4(1.0, x, x * x, x * x * x); - let v2 = glam::vec2(v4.z, v4.w) * v4.z; - - // Above sources are not explicit about it but this color is seemingly already in sRGB - // gamma space. - [ - ((v4.dot(RED_VEC4) + v2.dot(RED_VEC2)) * 255.0) as u8, - ((v4.dot(GREEN_VEC4) + v2.dot(GREEN_VEC2)) * 255.0) as u8, - ((v4.dot(BLUE_VEC4) + v2.dot(BLURE_VEC2)) * 255.0) as u8, - 255, - ] -} - struct DepthTexture { dimensions: glam::UVec2, data: DepthCloudDepthData, @@ -465,7 +432,7 @@ impl AlbedoTexture { let mut rgba8 = std::iter::repeat(0).take(size * 4).collect_vec(); spiral(dimensions).for_each(|(texcoords, d)| { let idx = ((texcoords.x + texcoords.y * dimensions.x) * 4) as usize; - rgba8[idx..idx + 4].copy_from_slice(turbo_color_map(d).as_slice()); + rgba8[idx..idx + 4].copy_from_slice(re_renderer::colormap_turbo_srgb(d).as_slice()); }); Self { dimensions, rgba8 } diff --git a/crates/re_renderer/shader/colormap.wgsl b/crates/re_renderer/shader/colormap.wgsl new file mode 100644 index 000000000000..759a7e044d5c --- /dev/null +++ b/crates/re_renderer/shader/colormap.wgsl @@ -0,0 +1,130 @@ +#import <./types.wgsl> +#import <./utils/srgb.wgsl> + +// NOTE: Keep in sync with `colormap.rs`! +const GRAYSCALE: u32 = 0u; +const COLORMAP_TURBO: u32 = 1u; +const COLORMAP_VIRIDIS: u32 = 2u; +const COLORMAP_PLASMA: u32 = 3u; +const COLORMAP_MAGMA: u32 = 4u; +const COLORMAP_INFERNO: u32 = 5u; + +fn colormap_srgb(which: u32, t: f32) -> Vec3 { + if which == COLORMAP_TURBO { + return colormap_turbo(t); + } else if which == COLORMAP_VIRIDIS { + return colormap_viridis(t); + } else if which == COLORMAP_PLASMA { + return colormap_plasma(t); + } else if which == COLORMAP_MAGMA { + return colormap_magma(t); + } else if which == COLORMAP_INFERNO { + return colormap_inferno(t); + } else { // assume grayscale + return linear_from_srgb(Vec3(t)); + } +} + +// --- Turbo color map --- + +// Polynomial approximation in GLSL for the Turbo colormap. +// Taken from https://gist.github.com/mikhailov-work/0d177465a8151eb6ede1768d51d476c7. +// Original LUT: https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f. +// +// Copyright 2019 Google LLC. +// SPDX-License-Identifier: Apache-2.0 +// +// Authors: +// Colormap Design: Anton Mikhailov (mikhailov@google.com) +// GLSL Approximation: Ruofei Du (ruofei@google.com) + +/// Returns a normalized sRGB polynomial approximation from Turbo color map, assuming `t` is +/// normalized (it will be saturated no matter what). +fn colormap_turbo_srgb(t: f32) -> Vec3 { + let r4 = Vec4(0.13572138, 4.61539260, -42.66032258, 132.13108234); + let g4 = Vec4(0.09140261, 2.19418839, 4.84296658, -14.18503333); + let b4 = Vec4(0.10667330, 12.64194608, -60.58204836, 110.36276771); + let r2 = Vec2(-152.94239396, 59.28637943); + let g2 = Vec2(4.27729857, 2.82956604); + let b2 = Vec2(-89.90310912, 27.34824973); + + let t = saturate(t); + let v4 = vec4(1.0, t, t * t, t * t * t); + let v2 = v4.zw * v4.z; + + return vec3( + dot(v4, r4) + dot(v2, r2), + dot(v4, g4) + dot(v2, g2), + dot(v4, b4) + dot(v2, b2) + ); +} + +// --- Matplotlib color maps --- + +// Polynomials fitted to matplotlib colormaps, taken from https://www.shadertoy.com/view/WlfXRN. +// +// License CC0 (public domain) +// https://creativecommons.org/share-your-work/public-domain/cc0/ +// +// Similar to https://www.shadertoy.com/view/XtGGzG but with a couple small differences: +// - use degree 6 instead of degree 5 polynomials +// - use nested horner representation for polynomials +// - polynomials were fitted to minimize maximum error (as opposed to least squares) +// +// Data fitted from https://github.com/BIDS/colormap/blob/master/colormaps.py (CC0). + +/// Returns a normalized sRGB polynomial approximation from Viridis color map, assuming `t` is +/// normalized (it will be saturated no matter what). +fn colormap_viridis_srgb(t: f32) -> Vec3 { + let c0 = Vec3(0.2777273272234177, 0.005407344544966578, 0.3340998053353061); + let c1 = Vec3(0.1050930431085774, 1.404613529898575, 1.384590162594685); + let c2 = Vec3(-0.3308618287255563, 0.214847559468213, 0.09509516302823659); + let c3 = Vec3(-4.634230498983486, -5.799100973351585, -19.33244095627987); + let c4 = Vec3(6.228269936347081, 14.17993336680509, 56.69055260068105); + let c5 = Vec3(4.776384997670288, -13.74514537774601, -65.35303263337234); + let c6 = Vec3(-5.435455855934631, 4.645852612178535, 26.3124352495832); + let t = saturate(t); + return c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * c6))))); +} + +/// Returns a normalized sRGB polynomial approximation from Plasma color map, assuming `t` is +/// normalized (it will be saturated no matter what). +fn colormap_plasma_srgb(t: f32) -> Vec3 { + let c0 = Vec3(0.05873234392399702, 0.02333670892565664, 0.5433401826748754); + let c1 = Vec3(2.176514634195958, 0.2383834171260182, 0.7539604599784036); + let c2 = Vec3(-2.689460476458034, -7.455851135738909, 3.110799939717086); + let c3 = Vec3(6.130348345893603, 42.3461881477227, -28.51885465332158); + let c4 = Vec3(-11.10743619062271, -82.66631109428045, 60.13984767418263); + let c5 = Vec3(10.02306557647065, 71.41361770095349, -54.07218655560067); + let c6 = Vec3(-3.658713842777788, -22.93153465461149, 18.19190778539828); + let t = saturate(t); + return c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * c6))))); +} + +/// Returns a normalized sRGB polynomial approximation from Magma color map, assuming `t` is +/// normalized (it will be saturated no matter what). +fn colormap_magma_srgb(t: f32) -> Vec3 { + let c0 = Vec3(-0.002136485053939582, -0.000749655052795221, -0.005386127855323933); + let c1 = Vec3(0.2516605407371642, 0.6775232436837668, 2.494026599312351); + let c2 = Vec3(8.353717279216625, -3.577719514958484, 0.3144679030132573); + let c3 = Vec3(-27.66873308576866, 14.26473078096533, -13.64921318813922); + let c4 = Vec3(52.17613981234068, -27.94360607168351, 12.94416944238394); + let c5 = Vec3(-50.76852536473588, 29.04658282127291, 4.23415299384598); + let c6 = Vec3(18.65570506591883, -11.48977351997711, -5.601961508734096); + let t = saturate(t); + return c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * c6))))); +} + +/// Returns a normalized sRGB polynomial approximation from Inferno color map, assuming `t` is +/// normalized (it will be saturated no matter what). +fn colormap_inferno_srgb(t: f32) -> Vec3 { + let c0 = Vec3(0.0002189403691192265, 0.001651004631001012, -0.01948089843709184); + let c1 = Vec3(0.1065134194856116, 0.5639564367884091, 3.932712388889277); + let c2 = Vec3(11.60249308247187, -3.972853965665698, -15.9423941062914); + let c3 = Vec3(-41.70399613139459, 17.43639888205313, 44.35414519872813); + let c4 = Vec3(77.162935699427, -33.40235894210092, -81.80730925738993); + let c5 = Vec3(-71.31942824499214, 32.62606426397723, 73.20951985803202); + let c6 = Vec3(25.13112622477341, -12.24266895238567, -23.07032500287172); + let t = saturate(t); + return c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * c6))))); +} diff --git a/crates/re_renderer/src/colormap.rs b/crates/re_renderer/src/colormap.rs new file mode 100644 index 000000000000..443e9da9b7d1 --- /dev/null +++ b/crates/re_renderer/src/colormap.rs @@ -0,0 +1,160 @@ +#![allow(clippy::excessive_precision)] + +use glam::{Vec2, Vec3A, Vec4, Vec4Swizzles}; + +// --- + +// NOTE: Keep in sync with `colormap.wgsl`! +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[repr(u32)] +pub enum ColorMap { + Grayscale = 0, + ColorMapTurbo = 1, + ColorMapViridis = 2, + ColorMapPlasma = 3, + ColorMapMagma = 4, + ColorMapInferno = 5, +} + +pub fn colormap_srgb(which: ColorMap, t: f32) -> [u8; 4] { + match which { + ColorMap::Grayscale => grayscale_srgb(t), + ColorMap::ColorMapTurbo => colormap_turbo_srgb(t), + ColorMap::ColorMapViridis => colormap_viridis_srgb(t), + ColorMap::ColorMapPlasma => colormap_plasma_srgb(t), + ColorMap::ColorMapMagma => colormap_magma_srgb(t), + ColorMap::ColorMapInferno => colormap_inferno_srgb(t), + } +} + +/// Returns an sRGB gray value, assuming `t` is normalized. +pub fn grayscale_srgb(t: f32) -> [u8; 4] { + debug_assert!((0.0..=1.0).contains(&t)); + + let t = t.powf(2.2); + let t = ((t * u8::MAX as f32) + 0.5) as u8; + + [t, t, t, t] +} + +// --- Turbo color map --- + +// Polynomial approximation in GLSL for the Turbo colormap. +// Taken from https://gist.github.com/mikhailov-work/0d177465a8151eb6ede1768d51d476c7. +// Original LUT: https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f. +// +// Copyright 2019 Google LLC. +// SPDX-License-Identifier: Apache-2.0 +// +// Authors: +// Colormap Design: Anton Mikhailov (mikhailov@google.com) +// GLSL Approximation: Ruofei Du (ruofei@google.com) + +/// Returns sRGB polynomial approximation from Turbo color map, assuming `t` is normalized. +pub fn colormap_turbo_srgb(t: f32) -> [u8; 4] { + const R4: Vec4 = Vec4::new(0.13572138, 4.61539260, -42.66032258, 132.13108234); + const G4: Vec4 = Vec4::new(0.09140261, 2.19418839, 4.84296658, -14.18503333); + const B4: Vec4 = Vec4::new(0.10667330, 12.64194608, -60.58204836, 110.36276771); + + const R2: Vec2 = Vec2::new(-152.94239396, 59.28637943); + const G2: Vec2 = Vec2::new(4.27729857, 2.82956604); + const B2: Vec2 = Vec2::new(-89.90310912, 27.34824973); + + debug_assert!((0.0..=1.0).contains(&t)); + + let v4 = glam::vec4(1.0, t, t * t, t * t * t); + let v2 = v4.zw() * v4.z; + + [ + ((v4.dot(R4) + v2.dot(R2)) * 255.0) as u8, + ((v4.dot(G4) + v2.dot(G2)) * 255.0) as u8, + ((v4.dot(B4) + v2.dot(B2)) * 255.0) as u8, + 255, + ] +} + +// --- Matplotlib color maps --- + +// Polynomials fitted to matplotlib colormaps, taken from https://www.shadertoy.com/view/WlfXRN. +// +// License CC0 (public domain) +// https://creativecommons.org/share-your-work/public-domain/cc0/ +// +// Similar to https://www.shadertoy.com/view/XtGGzG but with a couple small differences: +// - use degree 6 instead of degree 5 polynomials +// - use nested horner representation for polynomials +// - polynomials were fitted to minimize maximum error (as opposed to least squares) +// +// Data fitted from https://github.com/BIDS/colormap/blob/master/colormaps.py (CC0). + +/// Returns sRGB polynomial approximation from Viridis color map, assuming `t` is normalized. +pub fn colormap_viridis_srgb(t: f32) -> [u8; 4] { + const C0: Vec3A = Vec3A::new(0.2777273272234177, 0.005407344544966578, 0.3340998053353061); + const C1: Vec3A = Vec3A::new(0.1050930431085774, 1.404613529898575, 1.384590162594685); + const C2: Vec3A = Vec3A::new(-0.3308618287255563, 0.214847559468213, 0.09509516302823659); + const C3: Vec3A = Vec3A::new(-4.634230498983486, -5.799100973351585, -19.33244095627987); + const C4: Vec3A = Vec3A::new(6.228269936347081, 14.17993336680509, 56.69055260068105); + const C5: Vec3A = Vec3A::new(4.776384997670288, -13.74514537774601, -65.35303263337234); + const C6: Vec3A = Vec3A::new(-5.435455855934631, 4.645852612178535, 26.3124352495832); + + debug_assert!((0.0..=1.0).contains(&t)); + + let c = C0 + t * (C1 + t * (C2 + t * (C3 + t * (C4 + t * (C5 + t * C6))))); + + let c = c * 255.0; + [c.x as u8, c.y as u8, c.z as u8, 255] +} + +/// Returns sRGB polynomial approximation from Plasma color map, assuming `t` is normalized. +pub fn colormap_plasma_srgb(t: f32) -> [u8; 4] { + const C0: Vec3A = Vec3A::new(0.05873234392399702, 0.02333670892565664, 0.5433401826748754); + const C1: Vec3A = Vec3A::new(2.176514634195958, 0.2383834171260182, 0.7539604599784036); + const C2: Vec3A = Vec3A::new(-2.689460476458034, -7.455851135738909, 3.110799939717086); + const C3: Vec3A = Vec3A::new(6.130348345893603, 42.3461881477227, -28.51885465332158); + const C4: Vec3A = Vec3A::new(-11.10743619062271, -82.66631109428045, 60.13984767418263); + const C5: Vec3A = Vec3A::new(10.02306557647065, 71.41361770095349, -54.07218655560067); + const C6: Vec3A = Vec3A::new(-3.658713842777788, -22.93153465461149, 18.19190778539828); + + debug_assert!((0.0..=1.0).contains(&t)); + + let c = C0 + t * (C1 + t * (C2 + t * (C3 + t * (C4 + t * (C5 + t * C6))))); + + let c = c * 255.0; + [c.x as u8, c.y as u8, c.z as u8, 255] +} + +/// Returns sRGB polynomial approximation from Magma color map, assuming `t` is normalized. +pub fn colormap_magma_srgb(t: f32) -> [u8; 4] { + const C0: Vec3A = Vec3A::new(-0.002136485053939, -0.000749655052795, -0.005386127855323); + const C1: Vec3A = Vec3A::new(0.2516605407371642, 0.6775232436837668, 2.494026599312351); + const C2: Vec3A = Vec3A::new(8.353717279216625, -3.577719514958484, 0.3144679030132573); + const C3: Vec3A = Vec3A::new(-27.66873308576866, 14.26473078096533, -13.64921318813922); + const C4: Vec3A = Vec3A::new(52.17613981234068, -27.94360607168351, 12.94416944238394); + const C5: Vec3A = Vec3A::new(-50.76852536473588, 29.04658282127291, 4.23415299384598); + const C6: Vec3A = Vec3A::new(18.65570506591883, -11.48977351997711, -5.601961508734096); + + debug_assert!((0.0..=1.0).contains(&t)); + + let c = C0 + t * (C1 + t * (C2 + t * (C3 + t * (C4 + t * (C5 + t * C6))))); + + let c = c * 255.0; + [c.x as u8, c.y as u8, c.z as u8, 255] +} + +/// Returns sRGB polynomial approximation from Inferno color map, assuming `t` is normalized. +pub fn colormap_inferno_srgb(t: f32) -> [u8; 4] { + const C0: Vec3A = Vec3A::new(0.00021894036911922, 0.0016510046310010, -0.019480898437091); + const C1: Vec3A = Vec3A::new(0.1065134194856116, 0.5639564367884091, 3.932712388889277); + const C2: Vec3A = Vec3A::new(11.60249308247187, -3.972853965665698, -15.9423941062914); + const C3: Vec3A = Vec3A::new(-41.70399613139459, 17.43639888205313, 44.35414519872813); + const C4: Vec3A = Vec3A::new(77.162935699427, -33.40235894210092, -81.80730925738993); + const C5: Vec3A = Vec3A::new(-71.31942824499214, 32.62606426397723, 73.20951985803202); + const C6: Vec3A = Vec3A::new(25.13112622477341, -12.24266895238567, -23.07032500287172); + + debug_assert!((0.0..=1.0).contains(&t)); + + let c = C0 + t * (C1 + t * (C2 + t * (C3 + t * (C4 + t * (C5 + t * C6))))); + + let c = c * 255.0; + [c.x as u8, c.y as u8, c.z as u8, 255] +} diff --git a/crates/re_renderer/src/lib.rs b/crates/re_renderer/src/lib.rs index 5a73c9442a8e..c2afaab57437 100644 --- a/crates/re_renderer/src/lib.rs +++ b/crates/re_renderer/src/lib.rs @@ -15,6 +15,7 @@ pub mod resource_managers; pub mod view_builder; mod allocator; +mod colormap; mod context; mod debug_label; mod depth_offset; @@ -25,6 +26,10 @@ mod size; mod wgpu_buffer_types; mod wgpu_resources; +pub use colormap::{ + colormap_inferno_srgb, colormap_magma_srgb, colormap_plasma_srgb, colormap_srgb, + colormap_turbo_srgb, colormap_viridis_srgb, grayscale_srgb, ColorMap, +}; pub use context::RenderContext; pub use debug_label::DebugLabel; pub use depth_offset::DepthOffset; diff --git a/crates/re_renderer/src/workspace_shaders.rs b/crates/re_renderer/src/workspace_shaders.rs index 47b6b0520f8a..c15de19e70f1 100644 --- a/crates/re_renderer/src/workspace_shaders.rs +++ b/crates/re_renderer/src/workspace_shaders.rs @@ -13,6 +13,12 @@ pub fn init() { use crate::file_system::FileSystem as _; let fs = crate::MemFileSystem::get(); + { + let virtpath = Path::new("shader/colormap.wgsl"); + let content = include_str!("../shader/colormap.wgsl").into(); + fs.create_file(virtpath, content).unwrap(); + } + { let virtpath = Path::new("shader/composite.wgsl"); let content = include_str!("../shader/composite.wgsl").into(); diff --git a/crates/re_sdk/src/demo_util.rs b/crates/re_sdk/src/demo_util.rs index e44c2cb3c439..2389b43e381a 100644 --- a/crates/re_sdk/src/demo_util.rs +++ b/crates/re_sdk/src/demo_util.rs @@ -92,7 +92,7 @@ pub fn color_spiral( let colors = (0..num_points) .map(move |i| { - re_viewer::color_map::turbo_color_map(i as f32 / num_points as f32).to_array() + re_viewer::external::re_renderer::colormap_turbo_srgb(i as f32 / num_points as f32) }) .collect(); diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 88c0bf28316d..54f98c7abb79 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -11,7 +11,6 @@ mod remote_viewer_app; mod ui; mod viewer_analytics; -pub use self::misc::color_map; pub(crate) use misc::{mesh_loader, Item, TimeControl, TimeView, ViewerContext}; use re_log_types::PythonVersion; pub(crate) use ui::{event_log_view, memory_panel, selection_panel, time_panel, UiVerbosity}; @@ -22,6 +21,7 @@ pub use remote_viewer_app::RemoteViewerApp; pub mod external { pub use eframe; pub use egui; + pub use re_renderer; } // ---------------------------------------------------------------------------- diff --git a/crates/re_viewer/src/misc/caches/tensor_image_cache.rs b/crates/re_viewer/src/misc/caches/tensor_image_cache.rs index 3ada71f68ed6..924362da3237 100644 --- a/crates/re_viewer/src/misc/caches/tensor_image_cache.rs +++ b/crates/re_viewer/src/misc/caches/tensor_image_cache.rs @@ -472,7 +472,9 @@ fn dynamic_image_to_egui_color_image( pixels: gray .pixels() .map(|pixel| { - crate::misc::color_map::turbo_color_map((pixel[0] as f32) / (u16::MAX as f32)) + let [r, g, b, _] = + re_renderer::colormap_turbo_srgb((pixel[0] as f32) / (u16::MAX as f32)); + egui::Color32::from_rgb(r, g, b) }) .collect(), }, diff --git a/crates/re_viewer/src/misc/color_map.rs b/crates/re_viewer/src/misc/color_map.rs deleted file mode 100644 index 26613c06dffd..000000000000 --- a/crates/re_viewer/src/misc/color_map.rs +++ /dev/null @@ -1,305 +0,0 @@ -use glam::{Vec2, Vec4}; - -/// Converts float from 0.0..=1.0 into a color using Turbo. -/// -/// The Turbo color map described [here](https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html) -/// -/// Turbo color map is originally a lookup table! -/// I.e. for any value not captured we'd need to interpolate. -/// -/// Instead, we use this polynomial approximation. -/// [see here](https://gist.github.com/mikhailov-work/0d177465a8151eb6ede1768d51d476c7) -#[allow(clippy::excessive_precision)] -pub fn turbo_color_map(x: f32) -> egui::Color32 { - const RED_VEC4: Vec4 = Vec4::new(0.13572138, 4.61539260, -42.66032258, 132.13108234); - const GREEN_VEC4: Vec4 = Vec4::new(0.09140261, 2.19418839, 4.84296658, -14.18503333); - const BLUE_VEC4: Vec4 = Vec4::new(0.10667330, 12.64194608, -60.58204836, 110.36276771); - const RED_VEC2: Vec2 = Vec2::new(-152.94239396, 59.28637943); - const GREEN_VEC2: Vec2 = Vec2::new(4.27729857, 2.82956604); - const BLURE_VEC2: Vec2 = Vec2::new(-89.90310912, 27.34824973); - - let v4 = glam::vec4(1.0, x, x * x, x * x * x); - let v2 = glam::vec2(v4.z, v4.w) * v4.z; - - // Above sources are not explicit about it but this color is seemingly already in sRGB gamma space. - egui::Color32::from_rgb( - ((v4.dot(RED_VEC4) + v2.dot(RED_VEC2)) * 255.0) as u8, - ((v4.dot(GREEN_VEC4) + v2.dot(GREEN_VEC2)) * 255.0) as u8, - ((v4.dot(BLUE_VEC4) + v2.dot(BLURE_VEC2)) * 255.0) as u8, - ) -} - -/// LUT as defined [here](https://github.com/sjmgarnier/viridisLite/blob/ffc7061/R/zzz.R) -/// -/// Converted to bytes using this python snippet: -/// ```python -/// for (r, g, b, asdf) in zip(R, G, B, opt): -// if asdf == 'D': -// print("[{}, {}, {}],".format(int(r * 255.0 + 0.5), int(g * 255.0 + 0.5), int(b * 255.0 + 0.5))) -/// ``` -const VIRIDIS_SRGB_BYTES: [[u8; 3]; 256] = [ - [68, 1, 84], - [68, 2, 86], - [69, 4, 87], - [69, 5, 89], - [70, 7, 90], - [70, 8, 92], - [70, 10, 93], - [70, 11, 94], - [71, 13, 96], - [71, 14, 97], - [71, 16, 99], - [71, 17, 100], - [71, 19, 101], - [72, 20, 103], - [72, 22, 104], - [72, 23, 105], - [72, 24, 106], - [72, 26, 108], - [72, 27, 109], - [72, 28, 110], - [72, 29, 111], - [72, 31, 112], - [72, 32, 113], - [72, 33, 115], - [72, 35, 116], - [72, 36, 117], - [72, 37, 118], - [72, 38, 119], - [72, 40, 120], - [72, 41, 121], - [71, 42, 122], - [71, 44, 122], - [71, 45, 123], - [71, 46, 124], - [71, 47, 125], - [70, 48, 126], - [70, 50, 126], - [70, 51, 127], - [70, 52, 128], - [69, 53, 129], - [69, 55, 129], - [69, 56, 130], - [68, 57, 131], - [68, 58, 131], - [68, 59, 132], - [67, 61, 132], - [67, 62, 133], - [66, 63, 133], - [66, 64, 134], - [66, 65, 134], - [65, 66, 135], - [65, 68, 135], - [64, 69, 136], - [64, 70, 136], - [63, 71, 136], - [63, 72, 137], - [62, 73, 137], - [62, 74, 137], - [62, 76, 138], - [61, 77, 138], - [61, 78, 138], - [60, 79, 138], - [60, 80, 139], - [59, 81, 139], - [59, 82, 139], - [58, 83, 139], - [58, 84, 140], - [57, 85, 140], - [57, 86, 140], - [56, 88, 140], - [56, 89, 140], - [55, 90, 140], - [55, 91, 141], - [54, 92, 141], - [54, 93, 141], - [53, 94, 141], - [53, 95, 141], - [52, 96, 141], - [52, 97, 141], - [51, 98, 141], - [51, 99, 141], - [50, 100, 142], - [50, 101, 142], - [49, 102, 142], - [49, 103, 142], - [49, 104, 142], - [48, 105, 142], - [48, 106, 142], - [47, 107, 142], - [47, 108, 142], - [46, 109, 142], - [46, 110, 142], - [46, 111, 142], - [45, 112, 142], - [45, 113, 142], - [44, 113, 142], - [44, 114, 142], - [44, 115, 142], - [43, 116, 142], - [43, 117, 142], - [42, 118, 142], - [42, 119, 142], - [42, 120, 142], - [41, 121, 142], - [41, 122, 142], - [41, 123, 142], - [40, 124, 142], - [40, 125, 142], - [39, 126, 142], - [39, 127, 142], - [39, 128, 142], - [38, 129, 142], - [38, 130, 142], - [38, 130, 142], - [37, 131, 142], - [37, 132, 142], - [37, 133, 142], - [36, 134, 142], - [36, 135, 142], - [35, 136, 142], - [35, 137, 142], - [35, 138, 141], - [34, 139, 141], - [34, 140, 141], - [34, 141, 141], - [33, 142, 141], - [33, 143, 141], - [33, 144, 141], - [33, 145, 140], - [32, 146, 140], - [32, 146, 140], - [32, 147, 140], - [31, 148, 140], - [31, 149, 139], - [31, 150, 139], - [31, 151, 139], - [31, 152, 139], - [31, 153, 138], - [31, 154, 138], - [30, 155, 138], - [30, 156, 137], - [30, 157, 137], - [31, 158, 137], - [31, 159, 136], - [31, 160, 136], - [31, 161, 136], - [31, 161, 135], - [31, 162, 135], - [32, 163, 134], - [32, 164, 134], - [33, 165, 133], - [33, 166, 133], - [34, 167, 133], - [34, 168, 132], - [35, 169, 131], - [36, 170, 131], - [37, 171, 130], - [37, 172, 130], - [38, 173, 129], - [39, 173, 129], - [40, 174, 128], - [41, 175, 127], - [42, 176, 127], - [44, 177, 126], - [45, 178, 125], - [46, 179, 124], - [47, 180, 124], - [49, 181, 123], - [50, 182, 122], - [52, 182, 121], - [53, 183, 121], - [55, 184, 120], - [56, 185, 119], - [58, 186, 118], - [59, 187, 117], - [61, 188, 116], - [63, 188, 115], - [64, 189, 114], - [66, 190, 113], - [68, 191, 112], - [70, 192, 111], - [72, 193, 110], - [74, 193, 109], - [76, 194, 108], - [78, 195, 107], - [80, 196, 106], - [82, 197, 105], - [84, 197, 104], - [86, 198, 103], - [88, 199, 101], - [90, 200, 100], - [92, 200, 99], - [94, 201, 98], - [96, 202, 96], - [99, 203, 95], - [101, 203, 94], - [103, 204, 92], - [105, 205, 91], - [108, 205, 90], - [110, 206, 88], - [112, 207, 87], - [115, 208, 86], - [117, 208, 84], - [119, 209, 83], - [122, 209, 81], - [124, 210, 80], - [127, 211, 78], - [129, 211, 77], - [132, 212, 75], - [134, 213, 73], - [137, 213, 72], - [139, 214, 70], - [142, 214, 69], - [144, 215, 67], - [147, 215, 65], - [149, 216, 64], - [152, 216, 62], - [155, 217, 60], - [157, 217, 59], - [160, 218, 57], - [162, 218, 55], - [165, 219, 54], - [168, 219, 52], - [170, 220, 50], - [173, 220, 48], - [176, 221, 47], - [178, 221, 45], - [181, 222, 43], - [184, 222, 41], - [186, 222, 40], - [189, 223, 38], - [192, 223, 37], - [194, 223, 35], - [197, 224, 33], - [200, 224, 32], - [202, 225, 31], - [205, 225, 29], - [208, 225, 28], - [210, 226, 27], - [213, 226, 26], - [216, 226, 25], - [218, 227, 25], - [221, 227, 24], - [223, 227, 24], - [226, 228, 24], - [229, 228, 25], - [231, 228, 25], - [234, 229, 26], - [236, 229, 27], - [239, 229, 28], - [241, 229, 29], - [244, 230, 30], - [246, 230, 32], - [248, 230, 33], - [251, 231, 35], - [253, 231, 37], -]; - -/// Given a value in [0, 1], output `sRGB` in Viridis color map. -#[inline] -pub fn viridis_color_map(t: f32) -> [u8; 3] { - // TODO(andreas): interpolate - let index = (t * 255.0 + 0.5) as usize; - VIRIDIS_SRGB_BYTES[index.min(255)] -} diff --git a/crates/re_viewer/src/misc/mod.rs b/crates/re_viewer/src/misc/mod.rs index 603352f48357..d041edbc479c 100644 --- a/crates/re_viewer/src/misc/mod.rs +++ b/crates/re_viewer/src/misc/mod.rs @@ -1,6 +1,5 @@ mod app_options; pub mod caches; -pub mod color_map; pub mod format_time; mod item; pub(crate) mod mesh_loader; diff --git a/crates/re_viewer/src/ui/view_tensor/ui.rs b/crates/re_viewer/src/ui/view_tensor/ui.rs index 35e96c447efb..405cbf85523e 100644 --- a/crates/re_viewer/src/ui/view_tensor/ui.rs +++ b/crates/re_viewer/src/ui/view_tensor/ui.rs @@ -389,9 +389,12 @@ impl ColorMapping { let lum = (f * 255.0 + 0.5) as u8; Color32::from_gray(lum) } - ColorMap::Turbo => crate::misc::color_map::turbo_color_map(f), + ColorMap::Turbo => { + let [r, g, b, _] = re_renderer::colormap_turbo_srgb(f); + Color32::from_rgb(r, g, b) + } ColorMap::Virdis => { - let [r, g, b] = crate::misc::color_map::viridis_color_map(f); + let [r, g, b, _] = re_renderer::colormap_viridis_srgb(f); Color32::from_rgb(r, g, b) } }