Volume rendering provides a very high quality rendering. The basic goal of the volume ray casting is to allow the best use of the 3D data and not attempt to use any geometric structure on it. It solves one of the most important limitations of surface extraction techniques.
Ray casting is an algorithm to perform the direct volume rendering. The core of the algorithm is sending one ray, R, per pixel from the camera and take samples along the ray inside a volume. At each sample there is an amount of illumination I(x,y,z), from the light sources. Not all illumination is scattered in the direction to the camera. It depends on the local density D(x,y,z) at the point.
Maximum Intensity Projection uses the highest value that is encountered along the ray to calculate the final color[1]. This technique can be used to visualize blood vessels since they have high values caused by substance injected into the vein. The blood vessel will be visible if the surrounding tissues have the lower values.
In this post i am using the MIP(maximum intensity projection) ray casting technique. When i render the original volume size of 256X256X256 and parallelize it, i do not see much of speed-up, only fractions of second. To realize any significant speed-up within the rendering, i scale the volume 2.5 times in each dimension and then i render it with and without parallelization. Scaling operation is just one of the affine transformation operations to make the volume larger in each dimension so that the boundary becomes larger and thus takes more time to traverse. It took 7 seconds to render the image as shown below, while rendering with the parallel pragmas enable it to complete the rendering in 2 seconds.
The main rendering algorithm contains 3 loops as we are traversing through the volumetric data. The OpenMP pragmas will be only the first outer loop, since we need to allocate rows of the frame buffer to different threads. Even though OpenMP provides the data-sharing attribute rules that could be relied on, i prefer to use the default (none) clause instead. In this way i mention to the OpenMP that i take the sole responsibility of data sharing attributes and the reward is two-fold[2]. They are:
- We must carefully think about the usage of variables and this action help us to avoid mistakes.
- Explicitly mentioning the data sharing attributes is more subtle.
For good performance, it is good idea to use private variables as much as possible. I believe that i have managed to make the rendering faster by carefully considering which variables are going to be private or shared.
References
[1] Introduction to Volume Rendering.
[2] Using OpenMP: Portable Shared Memory Parallel Programming
No comments:
Post a Comment