Displaying Transparent Voxels

Started by
4 comments, last by myrdos 11 years, 5 months ago
I have some galaxy data that I'm trying to display in 3D. My program reads in a series of still images, and stacks them to make a cube, where each voxel is the pixel from the corresponding image.

I then apply transparency to display the 3D shape we're looking for. I'm using simple OpenGL cubes for my voxels, and I get a result like this:

simple_galaxy.png

The main problem is that I can see a grid of cube edges within the data. I've also noticed that the order in which I draw the layers matters - the red layer is on top of the green layer, but is drawn as if it were 'covered' by it. I'm using the following for my lighting and blending:


glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_TEXTURE_2D);

//### Re-normalize surface normals after scaling operations ###
glEnable(GL_NORMALIZE);

//### Configure the lighting model ###
glEnable(GL_LIGHTING);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

//### Enable smooth shading ###
glShadeModel(GL_SMOOTH);

//### Configure blending ###
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


1) Does anyone know how to get rid of the grid-like effect?

2) Is there anything I should be changing in my blending configuration?

Any help is greatly appreciated!
Advertisement
This is a rather complex problem using triangle based rendering. Do you need volumetric type effects where the transparency is dependent on the ray distance? Are the volumes a uniform color usually?

One solution is to triangulate your meshes with the same color into single mesh objects and render both the back and front faces using a DX11 order independent transparency linked list approach storing the beginning and end of each volume then in a second pass change the rendering algorithm to use an opacity rendering equation like this.

The alternative is to raycast on the GPU using 3DDDA which requires DX10/11 hardware. You can use a similar opacity function as the one I linked as you raycast the volume.

Note there is a reason why you don't see this much in games. It requires rather advanced solutions to look correct.
If you have real still images, they are all oriented in the viewer direction? But you are drawing cubes with 6 sides, obviously oriented in 6 directions. Instead, for each voxel, draw the corresponding still image with the normal always pointing to the camera. That would take care of the grid look.

When using blending, you need to disable depth tests and sort the galaxies from far to near.

There is another trick you can do if your images contains stars, which are either fully transparent or not transparent at all. Turn off blending, enable depth tests, draw the images in any order, and have the fragment shader discard pixels with alpha==0. Even if the images are semi transparent, the approximation to discard pixels where "alpha<limit" can be good enough. It depends on what accuracy requirement you have on the final result. If you just want it to look nice, or if you actually want to study the real world using your image.

Consider use contemporary OpenGL instead of Legacy OpenGL, which opens up for for possibilities.
[size=2]Current project: Ephenation.
[size=2]Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/
If you dont need many stacked transparent pixels to look more opaque you can just not draw cube surfaces facing another same color (?) nontransparent surface

o3o

Take a look at this:

http://www.iquilezle.../volumesort.htm

This uses different indices for different view directions. This should work pretty well for your problem. You can reduce the amount of necessary index data by using instancing or something like that.
Thanks for all the replies!

##### Sirisian #####

> Do you need volumetric type effects where the transparency is dependent on the ray distance?
The transparency is based on the transparency of each pixel in the original 2D image - it varies from voxel to voxel.

> Are the volumes a uniform color usually?
We'll be applying a different colors to voxels based on their velocity in the galaxy.

> One solution is to triangulate your meshes...
Thanks for the links, I'll look into it!

##### larspensjo #####

> If you have real still images, they are all oriented in the viewer direction?
The voxels are being displayed in a 3D "Cave" system with head tracking. The galaxies will always be drawn at different angles, based on where the user is standing.

> But you are drawing cubes with 6 sides, obviously oriented in 6 directions. Instead, for each voxel, draw the corresponding still image with the normal always pointing to the camera. That would take care of the grid look.
So I would draw a square instead of a cube, with the surface normal pointed towards the user's eyes... seems promising!

> When using blending, you need to disable depth tests and sort the galaxies from far to near.
This could get intensive... right now I have about 24,000 voxels in my model. I'm currently performing checks if the voxel has an alpha value below some threshold, at which point I discard it (otherwise I'd have about 800,000 voxels!)

> Consider use contemporary OpenGL instead of Legacy OpenGL, which opens up for for possibilities.
I'd prefer to avoid this if possible, and look for a simple fix for now... what types of things would I be able to try with OpenGL 3?

##### Waterlimon #####

I'm afraid I don't follow!

##### Ginkgo #####

> From the link: Then, you can very easily sort this objects at virtually zero performance cost,
Sounds like what I need, I'll read up on it!

This topic is closed to new replies.

Advertisement