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

Visualize indexed quantities using a fixed color palette #289

Open
jdumas opened this issue Aug 14, 2024 · 2 comments
Open

Visualize indexed quantities using a fixed color palette #289

jdumas opened this issue Aug 14, 2024 · 2 comments

Comments

@jdumas
Copy link
Contributor

jdumas commented Aug 14, 2024

Hi! I was wondering if there's an easy to visualize discrete scalar attributes (e.g. facet coloring/clustering). It seems that scalar quantities are associated a continuous color map (like Viridis), but I'd like to use a discrete color palette instead (maybe using something from https://colorbrewer2.org?).

@nmwsharp
Copy link
Owner

There isn't a magic built-in function for this, but it's at the top of my to-implement list :)

I actually started some work for it, there's a shader function here

// Used to sample colors. Samples a series of most-distant values from a range [0,1]
// offset from a starting value 'start' and wrapped around. index=0 returns start.
// We only actually output distinct floats for the first 10 bits, then the pattern repeats.
//
// (same logic appears in color_management.cpp)
//
// Example: if start = 0, emits f(0, i) = {0, 1/2, 1/4, 3/4, 1/8, 5/8, 3/8, 7/8, ...}
float intToDistinctReal(float start, int index) {
const int NBitsUntilRepeat = 10;
if (index < 0) {
return 0.0f;
}
// Bit shifts to evaluate f()
float val = 0.f;
float p = 0.5f;
for(int iShift = 0; iShift < NBitsUntilRepeat; iShift++) { // unroll please
val += float((index % 2) == 1) * p;
index = index >> 1;
p /= 2.0;
}
// Apply modular offset
val = mod(val + start, 1.0);
return clamp(val, 0.f, 1.f);
}
that's used map integer values into distinct discrete values that can be sampled from the colormap. Right now it is only used for distinctly coloring UV map islands, however.

I want to expose this as an option for arbitrary scalar values which happen to be integers, but have not done so yet. There is also another (slightly more-difficult) step needed, to change the interpolation policy e.g. for vertex-valued integers on the mesh, so they get nearest-neighbor interpolated rather than linearly interpolated. That is possible within Polyscope's shaders but not implemented yet.

@jdumas
Copy link
Contributor Author

jdumas commented Aug 14, 2024

Thanks for the quick answer! I think an important feature for discrete colormaps is to have a way to either detect or specify the number of discrete values you want to use in the color palette. I'm not sure you need the intToDistinctReal function though, wouldn't it be enough to resize the colormap texture to have a width = to the number of discrete values you need?

Maybe once you have the nearest-neighbor interpolation, it's mostly a matter of having more helper functions to create custom discrete colormap textures (e.g. load from a 1D array instead of from a file, or create some colorbrewer palettes).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants