Perhaps the most common form of modelling and rendering in conputer graphics
involves geometric data made up of points, line, polygons, spheres, curved
surfaces, etc. However, there are many application where decomposing the
data to be rendered or visualised into those geometric forms is inconvenient
or downright inappropriate. An example of this type of data is commonly refered
to as volumetric data, in the simplest case this is a volume inside which
some scalar property such is density is known at every point (or at least
on a grid of some finite resolution).
Often an understanding of the distribution of density, say, within the volume can be obtained by deriving an isosurface. That is, a 3D contour is created at a selected density, the resulting surface shows all the regions that are more (or less) dense than the chosen contour level. This often works well for volumes with strong and obvious internal structure, for example, showing the bone from an MRI scan of a part of the human body. This method doesn't work well for volumes with more subtle variation or when multiple density ranges need to be shown or when illustrating multiple interacting scalar properties.
In these cases a more immediate method is chosen, the volume is rendered directly without decomposing it into geometric primitives. Typically the scalar property within the volume is assigned a colour and transparency depending on lookup tables, rays are traced into the volume and they are attenuated and coloured depending on the transparency of their route through the volume.
In the following example we will create an artificial density distribution within a 100x100x100 grid. While this is quite a coarse grid, the memory and processing required goes up by the third power of the linear dimension. So while a 1003 grid with one byte per grid cell (256 density levels) requires 1MB to store the data, a 3003 grid requires 27MB, and a 6003 grid requires 216MB.
The graph above shows the density distribution for this example, it is
the same along all three dimension of the grid. That is, the center of the
grid has the highest density and it drops of exponentially towards the
edges of the grid. Note that this is a very simple distribution and it
doesn't contain any of the artifacts and noise that volume distributions
in real applications have. It is however useful to use a simple distribution
that is totally understood when experimenting with volume rendering.
The vertical axis isn't shown with units because it isn't that important for this example. Because it is common to store 1 byte at each pixel, the scale in this case would be from 0 (vacuum say) to 255 (maximum density).
The most important aspect of volume rendering is specifying the transfer functions that map density (or other scalar variables) within the volume to colour and transparency. The example volume (Source Code) we're using here has a radial density falloff from the center, so if we make all densities perfectly transparent except for a narrow range of densities that we will make perfectly opaque, we should "see" a sphere when we render the volume. As expected this is shown below. Note that this sphere is hollow but we can't see into the inside because we made the density within a narrow range totally opaque.
The graph on the left above illustrates the transparency transfer function.
The horizontal axis is the density axes from 0 to 255 in this case.
The vertical axes is opacity that ranges from 0 (totally transparent)
to 1 (totally opaque).
The sharpness and bumpiness of the above rendering is a consequence of two factors, the discreteness of the data in this example (only 100x100x100 cells), and the sharpness of the transparency transfer function.
In this next case the transparency will be slowly decreased (opacity increased) from zero at 0 density. All cells with a density greater than some cutoff value will be totally transparent. The result should be a hollow sphere with a cloud-like surround.
The next case combines the last two transparency mappings just to illustrate that there is a transparent cloud. A range of high densities will be made totally opaque forming a ball as in the first example but smaller since the range of densities that are made opaque is higher.
Up to now we've just been considering a transparency map, we can also create
colour maps which are also functions of density. For this next case we can
make the center dense sphere blue by reducing the red and green components
of the same density range.
The top graph on the left below is the transparency map as before, the bottom graph is the colour transfer function. The vertical scale on the colour transfer function ranges from 0 (none of that colour component), to 1 (fully saturated component) in each of the three components, red, green, and blue.
And finally, by similar techniques we can make the transparent cloud-like surround reddish.
Volume rendering software distinguish themselves in various ways, some of these are discussed below.
As mentioned earlier, volume rendering often has to deal with large amounts of data and corresponding large processing demands. There have been some rapid advances made in reducing the rendering times, in particular the shear warp methods introduced a few years ago. There are also algorithms that make use of hardware alpha blending support on some platforms.
Due to the high processing and data requirements it is not unusual for volume renderers to provide support for distributed rendering both across single shared memory multiple processor machines and clusters. There are methods for not just distributing the processing but also splitting up the volume data across processors and combining the results at the end.
There is considerable artistic and design scope in the specification of transfer functions. Unlike the simplistic single transfer functions shown above, it is often necessary to combine a number of transfer functions. There are other transfer function methods such as gradient functions that map the gradient (rate of change) of the density to transparency and/or colour.
It isn't uncommon for there to be multiple scalar types within the volume. For example one might know the pressure and temperature within a volume. It is a non trivial programming and human interface issue how the user specifies multiple transfer functions for multiple variable volumes.
Most volume rendering package require that the data is provided on a grid, indeed many assume the data is on a regular (equal spaced) grid. This isn't often a serious issue as there are standard techniques for sampling on a grid if the data isn't too sparce.
A few free volume renderers for those who may like to experiment further.
"bob" from the Army High Performance Computing Research Center
"vfleet" from the Pittsburgh Supercomputing Center
"volvis" from SUNY Stony Brook
"NetV" from the San Diego Supercomputing Center
"VTK", the Visualisation ToolKit has volume rendering functionality