3D Volume Rendering

Hi everyone!

I would like to show a scalar field inside a cube. I have in an array the scalar value for each point in space and I would like to visualize it. I find the best approach would be to use volume rendering technique. There is an example of such task in Cinder? Otherwise I can use other techniques?

Thanks for your help
Andrea

If you have a 3D mesh of an arrow (which you can also make by combining a geom::Cone with a geom::Cylinder), you can use instanced rendering to render a bunch of them. If the array contains the normalized direction, you could convert them to a quaternion using glm::axisAngle and send the quaternions as vec4 to the vertex shader. In the vertex shader, you then use the quaternion to rotate each vertex of the arrow mesh. While a little complicated to implement, it should be blazingly fast.

-Paul

Hi Paul and thanks for the answer.
Correct me if I am wrong, but with the arrows I could show a vector field (with in each point an arrow). But to show a scalar field I need some metric such color for each point so I could modify your solution to instantiate different cube everyone with different color.
I have two question then:
1)I need to show a grid 300x300x300 (a lot of element) . Do you think with instantiate I can have a efficient solution?
2) otherwise I saw that there are several technique such isosurface or ray casting the volume (https://github.com/toolchainX/Volume_Rendering_Using_GLSL). In Cinder there is a sample of one of these methods? Otherwise I’ll try to implement them.

Anyway thanks for the help
Andrea

Hi,

wow… 300x300x300 is 27 million instances. I don’t think you can render that at interactive frame rates and even if you could it would not be very informative. Perhaps you could take the average of a 10x10x10 block of elements and represent them as a single arrow? That would result in 30x30x30 is 27,000 arrows, which most GPU’s should have no problem rendering.

Ray casting is powerful, but slow. Having 27 million objects to check against each ray would bring the fastest system to its knees, unless you can optimize the search by culling (frustum, occlusion) or binning, which is something you’d do on the CPU. I personally wouldn’t go there, it could easily eat up all your time.

Not sure how an iso-surface could be used to render a scalar field, but that’s because I have limited experience with it. I know other Cinder users have successfully implemented metaballs, marching cubes and iso-surfaces, but I don’t think their code is open source or compatible with the current Cinder version.

And sorry for the confusion about scalar/vector fields… I suppose scalars are easier to depict: you could use a simple cube and vary its size (float) or color (vec3). That would be a bit easier than drawing arrows using quaternions. Use the mentioned sample as a starting point for that. Use a cube instead of a teapot and you’re halfway there.

-Paul

I will try your suggestion!
Thanks for the help!

Andrea

Hi Andrea,

I have a gpu marching cube polygonizer for metaballs that I have been planning to release for a long time. It was written for Cinder 0.8.6, so it can take some time until I port it to 0.9.
It was based on this article:
http://www.icare3d.org/codes-and-projects/codes/opengl_geometry_shader_marching_cubes.html
I’m not sure it can handle a 300x300x300 field in real-time, though. I was testing it with 64x64x64.

-Gabor

Hi gabor_papp.
Thanks for your help. It is really interesting and could be very helpful.
I’ll try to have a look to the article and try to implement the solution in Cinder.
If you want to share the old code I can help in porting it in the new Cinder otherwise thanks anyway for the suggesion

-Andrea

There’s a couple of good methods you can use.
One would be to send the data over as a 3D texture for use in a shader. Miles has a great shader base I’ve used before (in cinder) here:
http://blog.mmacklin.com/2010/11/01/adventures-in-fluid-simulation/
which can also be extended for a solid-surface type of visual.

A grid of 300 may be quite heavy on the GPU, you might need to find a way to represent it in a smaller texture if at all possible, as the upload to GPU will be the bottleneck otherwise.

Otherwise you could look at implementing OpenVDB:
https://www.openvdb.org/

Which would probably be great tbh. I have limited experience with it, but its fairly straightforward to make a volume set out of your data and it comes with meshing tools that are very easy to get results with.

Shared it with you. Hope we can port it to v0.9 and release it soon.

-Gabor

FYI, the Cuda toolkit has a working sample of Volume Render. Maybe now a port to compute shaders isn’t that hard.

Agree that 300x300x300 is too big for realtime, also normally they use powers of 2 (32, 64,…,512,…etc) as it fits better in GPU memory (I don’t know if this is still valid).

edit: somebody uploaded to git https://github.com/phrb/intro-cuda/tree/master/src/cuda-samples/2_Graphics/volumeRender