Texture mapping problem with volume rendering

Hi All,

here is a problem with volume rendering that has been bothering me for a year. Presumably it has something to do with interpolation.

I am doing a volume rendering with texture mapping (actually also with raycasting). The dataset is a cubic, scalar, one component. The dataset is thresholded. Visible range (foreground) will be, say, -300 ~ 1000. Voxels outside of this range (background) is given -1024.

In order to render the dataset, I defined a color map covering the range (-1024 ~ 1024), and set the opacity map so that the range -1024~300 will be completely transparent. The color map defines -1024 as for example some red color. The interpolation for the textures are GL_LINEAR.

Here is the problem I have. The rendered object is surrounded by a thin redish layer, whose color is close to that corresponding to scalar value -1024. With different thresholds, the color will change but still be redish.

A more challenge scenario is for multiple volumes. Even though different color maps are given to the volumes, the background scalar values are all -1024, so all the volumes show as redish. Only cutting the image into half can reveal the inner color.

What I guess is that the interpolation at the border of the foreground causes the problem. It generates middle colors between the foreground and background. If this guess is correct, is there a way to tell OpenGL NOT to use some color values for interpolation?

Or maybe my volume rendering is not right at all to deal with the color and opacity?

This has been a big headache for me. Your help will be greatly appreciated.

Best regards,

Frank Gao

Quick fix : GL_CLAMP_TO_EDGE
Correct fix : specify an appropriate border (fully transparent), either with single color, or both ends.
http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml
http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml

“width of the texture image including the border if any. […] this value must be 2^n+2*border for some integer n.”

Wait, I tough you used 1D texturing after ray integration. Apparently you don’t, forget the texture borders then.

Well, you asked for it.
I don’t get why you want a red color at the background.
Why not simply assigning to the backgroud value the same color as your threshold value, -300, but completely transparent ?

Hi,

Thanks you very much for the reply. I am trying to investigate what you suggested.

Yes I can set the background color as that of -300. The problem is sometimes I have no idea what the lower end of the scalar values, for example, when the data is generated by a region growth, or dilate operation. Plus, if the boundary of the object has a value higher than -300, it still gives the surrounding layer.

BTW, I do not understand the concept of “border”. Forgive me I am not familiar with OpenGL. Will need to learn more about this concept.

Thanks again,

Frank

Ah so the problem comes from the threshold, which is unknown.
However if you are able to do a dilate, you can apply it to force outer cells immediately surrounding the threshold to the same color (but transparent) as the threshold.

To sum up, either you disable color interpolation, either you make sure to interpolate the threshold between 2 identical (or just similar, often a medium gray is enough, and less distracting than red) colors, but one full transparent.

Hehe, why did you post on the “advanced” forum then ??

Hi ZbuffeR,

setting GL_CLAMP_TO_EDGE did not seem to be a fix with my test. I checked my OPenGL version at rumtime. It is 2.1.1.

Thanks,

Frank

This is not a choice for the application.

All I want is to smooth the surface of the volume. Color interpolation seems to be the way to do this. glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST ) will give me an effect of small tiles.

Frank

About OpenGL texture borders : instead of specifying say a 64x64 texture, you send data for a 66x66 texture (so, the same with 1 pixel borders all around). It is mandatory for tiling textures seamlessly. Don’t worry, even Google Earth did not get it right :frowning:
So when you sample exactly at 0 or 1 texture coordinate, the color is interpolated between the texel inside (“edge”) and the texel outside, (“border”). If no texture border is specified, the default is black. That is why sometimes there is a grayish line around a textured quad.

The theory :
http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node64.html

The practice :
http://www.opengl.org/resources/code/samples/glut_examples/advanced/textile.c

But as I said, your problem is probably unrelated to borders, even if symptoms are similar.

If you did not already read these links, I found them highly interesting :
http://www.cs.utah.edu/~jmk/sigg_crs_02/courses_0067.html
http://www.vrvis.at/via/resources/PR-CBerger-2/index.html
http://www.vis.uni-stuttgart.de/~engel/pre-integrated/

So the border is actually the six faces of the cubical volume, right? But the problem I have is within the volume. I really hope somehow tell OpenGL cells with certain color should be a background (not border, right?).

Thanks a lot for the links. In the following link:
http://www.cs.utah.edu/~jmk/sigg_crs_02/course_42/course_42_notes_small.pdf

Page 72 seems to have something similar, but it considers the phenomena an advantage since the borders/silhouette are more visible. :smiley:

Hi,

You could do three easy things:

  1. Discard all fragments that have this value.
  2. fade the color map to 0 transparency when out of the threshold. (you should experiment with how many values you should fade).
  3. Use associative coloring (each color is multiply by its alpha) so you can alpha test directly.

Ido

Hi,

sounds good idea, and I will give it a try.

I would like to restate the problem as below:

For volume rendering, when the rendering threshold (say, the opacity map) is wider than the scalar range of the foreground of the dataset, the rendered object will have a surrounding layer with the color mixed/interpolated with that of the background.

After I realized that the problem could be restated like this, I really feel it is a request to tell OpenGL that certain value is background, and should not participate in the interpolation.

How do you think?

Thanks,

Frank

a request to tell OpenGL that certain value is background, and should not participate in the interpolation

Do the interpolation yourself in fragement shader, and discard if one of the texture sample equals this value. Be prepared to slower performance.
Beware though : preventing the linear interpolation on the object edges like this, will make it severely aliased.

Now I got the feeling that this is going to solve the problem, but to be honest I have to learn the shader first.

Thanks,

Frank