<p>It may be easier to compute the gradient on the CPU, even with 16bit precision the CPU can grind out a texture quickly. Then just upload that to the GPU as an image. Also, it doesn't sound like users will be able to pick a new color set every frame so its sounds a lot more natural to have a work flow of: Pick colors -&gt; Generate Image -&gt; upload to the GPU -&gt; use new palette to render.</p>
<p>Are the picked colors RGB choices? If yes then it does make sense to spread the color palette out as wide as possible (maybe even more then 16bits) 65536 pixels is just a drop in the bucket. And a nice wide color range could lead to less banding in the final image.</p>
<p>At some  level the code will have to narrow the range down to whatever the current precision is. If that is the table, and the table has 65536 positions, then the table might contain a lot of repeating colors, but it is easy to compute the table with a new range.</p>

CC BY-SA 4.0
2021-04-29T13:11:27.493Z
By spreading out the palette you mean physically the size of the palette or internally the bits? I don't need to go more than 16bits as volume data is either 8 or 16 bit
gallickgunner
CC BY-SA 4.0
2021-04-29T12:49:26.853Z
2021-04-29T12:49:26.853Z
pmw1234
<p>I'm working on a scientific visualization project and need to create a transfer function widget. The volume data is either in range <code>0-255</code> or it can be 16 bit i.e. <code>0-65535</code>. Now the main problem is in order to color certain sections, the user needs to be able to define certain control points with varying colors and the colors need to be smoothly transitioned between those control points. Then during rendering, we find the color for every isovalue through a texture lookup in a ramp texture and color the volume data.</p>
<p>I've decided to do cubic spline interpolation between these control points. My question is, how do I actually render and store this gradient in an Nx1 ramp texture. Firstly, regarding the rendering part. I'm using OpenGL but also Dear-ImGui for GUI. So I don't have low level access to rendering like vertex/fragment shader for rendering this gradient. Just low level functions like rendering lines/rectangles etc.</p>
<p>For 8 bit volumes, I could render 256 lines of thickness <code>gradient_width_in_pixels/256</code>. I think this would give me the look of a rectangular gradient? However suppose I have a 16 bit volume. The max value now is 65k. I could go on and convert it to <code>0-255</code> but let's say I don't because there would be a loss of precision as in the <code>0-255</code> scale 1 value represents approximately 256 values of <code>0-65535</code> scale. What if the user wanted to color within that range? <em><strong>What's the proper way to handle this scenario now?</strong></em></p>
<p>Secondly, regarding storing the gradient information. For 8bit datasets, again it'd seem pretty simple to just create an <code>256x1</code> texture. However the problem again rises for 16 bit datasets. 65k pixels don't sound good or are they okay? I know <code>65k x 1</code> texture is just a <code>256x256</code> texture but dunno if increasing only 1 dimension will cause problems.</p>
<p>EDIT: I thought I should clarify regarding rendering the gradient part and ask the question differently. What I wanna know is given a color control point at pixel coord (x1,y) and another point at (x2, y), how many lines of any thickness should I render to get a color gradient with smooth transition between those two colors?</p>

CC BY-SA 4.0
2022-09-28T00:07:41.153Z
The maximum texture dimension in most GPUs is 16K or 32K, so a 64K texture isn't going to fly I don't think. Regarding the gradient, if you're asking about how to render a gradient on screen so it will look visually smooth, ideally you would use dithering. If dithering is not possible, and you are not on an HDR / wide color gamut monitor, then the best you can do is one line for each 1 unit change in the 8-bit RGB values, which would mean at most 256 lines for each color segment of the gradient.
Nathan Reed
<rendering><texture><volume-rendering>
How to render and store a color gradient in a ramp texture for 16bit dataset?
gallickgunner
# How to render and store a color gradient in a ramp texture for 16bit dataset?

(Asked by: username_0 on 2021-04-29)

I'm working on a scientific visualization project and need to create a transfer function widget. The volume data is either in range `0-255` or it can be 16 bit i.e. `0-65535`. Now the main problem is in order to color certain sections, the user needs to be able to define certain control points with varying colors and the colors need to be smoothly transitioned between those control points. Then during rendering, we find the color for every isovalue through a texture lookup in a ramp texture and color the volume data.

I've decided to do cubic spline interpolation between these control points. My question is, how do I actually render and store this gradient in an Nx1 ramp texture. Firstly, regarding the rendering part. I'm using OpenGL but also Dear-ImGui for GUI. So I don't have low level access to rendering like vertex/fragment shader for rendering this gradient. Just low level functions like rendering lines/rectangles etc.

For 8 bit volumes, I could render 256 lines of thickness `gradient_width_in_pixels/256`. I think this would give me the look of a rectangular gradient? However suppose I have a 16 bit volume. The max value now is 65k. I could go on and convert it to `0-255` but let's say I don't because there would be a loss of precision as in the `0-255` scale 1 value represents approximately 256 values of `0-65535` scale. What if the user wanted to color within that range? ***What's the proper way to handle this scenario now?***

Secondly, regarding storing the gradient information. For 8bit datasets, again it'd seem pretty simple to just create an `256x1` texture. However the problem again rises for 16 bit datasets. 65k pixels don't sound good or are they okay? I know `65k x 1` texture is just a `256x256` texture but dunno if increasing only 1 dimension will cause problems.

EDIT: I thought I should clarify regarding rendering the gradient part and ask the question differently. What I wanna know is given a color control point at pixel coord (x1,y) and another point at (x2, y), how many lines of any thickness should I render to get a color gradient with smooth transition between those two colors?

**Tags:** rendering, texture, volume-rendering

> **Comments:**
> **username_1**: The maximum texture dimension in most GPUs is 16K or 32K, so a 64K texture isn't going to fly I don't think. Regarding the gradient, if you're asking about how to render a gradient on screen so it will look visually smooth, ideally you would use dithering. If dithering is not possible, and you are not on an HDR / wide color gamut monitor, then the best you can do is one line for each 1 unit change in the 8-bit RGB values, which would mean at most 256 lines for each color segment of the gradient.  

---

## 1 answers

### Answer by username_2 on 2021-04-29. Score: 1

It may be easier to compute the gradient on the CPU, even with 16bit precision the CPU can grind out a texture quickly. Then just upload that to the GPU as an image. Also, it doesn't sound like users will be able to pick a new color set every frame so its sounds a lot more natural to have a work flow of: Pick colors -> Generate Image -> upload to the GPU -> use new palette to render.

Are the picked colors RGB choices? If yes then it does make sense to spread the color palette out as wide as possible (maybe even more then 16bits) 65536 pixels is just a drop in the bucket. And a nice wide color range could lead to less banding in the final image.

At some level the code will have to narrow the range down to whatever the current precision is. If that is the table, and the table has 65536 positions, then the table might contain a lot of repeating colors, but it is easy to compute the table with a new range.

> **Comments:**
> **username_0**: By spreading out the palette you mean physically the size of the palette or internally the bits? I don't need to go more than 16bits as volume data is either 8 or 16 bit  

---

