next up previous contents index
Next: Synopsis Up: Cell Projection Previous: GPU-CPU Balanced Cell Projection   Contents   Index


Adaptive Transfer Function Sampling

Figure 1.1: The effect of aliasing of the transfer function. Both images have the same transfer function, which has a sharp opacity transition to highlight an isosurface. The rendering on the top samples the transfer function at only the vertices of the cells, which induces aliasing. The rendering on the bottom adaptively samples the transfer function.
Image bluntfin_tf_aliased.png Image bluntfin_tf_sampled.png
(a) Linearly interpolated colors and opacities. (b) Adaptively sampled transfer function.

One major problem of volume rendering systems is that of aliasing of the transfer function. Typically, we sample the transfer function at the vertices of cells and interpolate the colors. However, this sampling often completely misses transitions in the transfer function. As an example, consider Figure 1.1(a). Because it samples the transfer function at only cell vertices, the renderer completely misses sharp transitions in the transfer function within cells, leaving a blocky, blurry mess. Compare this result to the appropriate transfer function sampling in Figure 1.1(b).

Engel, Kraus, and Ertl [22] solve this problem using pre-integration. By performing the integration offline, the rendering system can afford to sample the transfer function tightly independent of how the model samples scalars. However, I choose to avoid pre-integration because of the high computational overhead required every time the transfer function changes. Furthermore, the accuracy of pre-integration is low and pre-integration precludes the use of multidimensional transfer functions [47,50], non-photorealistic rendering effects [21,43,44], and global illumination [19,37,51,113].

Williams, Max, and Stein [105] solve this same problem by splitting cells. They define their transfer functions as piecewise linear functions. Each control point, a point where the transfer function is nonlinear, defines an isosurface. They split the cells on these isosurfaces, yielding a linear interpolation of rendering parameters within the split cells. The problem with the Williams, Max, and Stein approach is that it also introduces a high overhead when the transfer function changes.

My approach is similar to that of Williams, Max, and Stein in that I split cells on the isosurfaces of transfer-function control points. Except, instead of splitting a cell geometrically, I clip the cell on the graphics card. To do the clipping I need to pass two more pieces of information, the two control points that are clipping the tetrahedron, to the graphics card. (Note that this added information increases the data sent to the card to 36 floats per tetrahedron.) If any control points lay within the scalar range of a tetrahedron, I render the tetrahedron multiple times with varying clipping parameters until the entire cell is rendered. The ATFS-ProjectClippedTet procedure formalizes how, given a tetrahedron and two control points, we can send the data to the graphics card.


\begin{codebox}
\Procname{$\proc{ATFS-ProjectClippedTet}(T,{c}_{\,\mathrm{f}},{...
...ndex $i$ \End
\li Send $\const{RenderTriangleStrip} + 6$\ indices
\end{codebox}

The ATFS-ProjectClippedTet procedure is identical to the Balanced-ProjectTet procedure with two exceptions. First, the two scalar values of the transfer function control points ( $ {c}_{\,\mathrm{f}}$ and $ {c}_{\,\mathrm{b}}$) are passed to the graphics card. Second, rather than send the scalar values themselves, lines 8 and 9 normalize the scalars to the two control points.

Using normalized scalar values provides two features. One feature is that all parts of the tetrahedron that we do not clip will have a normalized scalar value in the range $ [0,1]$, making it easier to identify the clipped regions. Another feature is that because the luminance and attenuation parameters will vary linearly with the scalars in the range between the two control points, we can use the normalized scalar to interpolate these parameters. Thus, we can store the transfer function in the graphics card as a set of control points and then pass $ {c}_{\,\mathrm{f}}$ and $ {c}_{\,\mathrm{b}}$ indices to the appropriate control point. This mode removes any error that might occur with sampling the transfer function because it does not sample the transfer function.

Of course, we still need to determine the front and back transfer-function control points ( $ {c}_{\,\mathrm{f}}$ and $ {c}_{\,\mathrm{b}}$) before calling ATFS-ProjectClippedTet. The procedure ATFS-ProjectTet extracts the appropriate control points and renders the clipped tetrahedra in back to front order.


\begin{codebox}
\Procname{$\proc{ATFS-ProjectTet}(T,\id{transfer-func})$}
\li ...
...b}})$ \li ${c}_{\,\mathrm{b}} \gets {c}_{\,\mathrm{f}}$ \End
\End
\end{codebox}

ATFS-ProjectTet first determines the range of scalar values within tetrahedron $ T$ and over which transfer-function control points the range lies (lines 1 and 2). The procedure then determines in which direction to traverse the control points by taking a dot product of the scalar gradient with the view vector (lines 3 and 4). Both branches of the statement starting on line 5 iterate over the control points and render each clipped piece of the tetrahedron in back-to-front order. If the blending requires front-to-back rendering rather than back-to-front rendering, then we can reverse the conditions of the statement.


\begin{codebox}
\Procname{$\proc{ATFS-VertProg}(\vec{v},d,\id{norm-{s}_{\,\math...
...id{norm-s}},
{c}_{\,\mathrm{f}},{c}_{\,\mathrm{b}},\id{iso-dist})$\end{codebox}

The vertex program for adaptive transfer function sampling, ATFS-VertProg, is much like Balanced-VertProg. ATFS-VertProg, of course, passes also the two control points. In addition, it calculates the distance between the two isosurfaces at the control points in line 6. These two isosurfaces are parallel planes, and thus does not change throughout the tetrahedron. However, by performing the calculation in the vertex program, we can avoid transmitting more information from the CPU to the GPU.

The way ATFS-VertProg determines the distance is not straightforward. It is constrained to use the information already passed to it. From lines 8 and 9 in ATFS-ProjectClippedTet, we know that $ \id{norm-s} = (s -
{c}_{\,\mathrm{f}})/({c}_{\,\mathrm{f}} - {c}_{\,\mathrm{b}})$. Consider the difference of the two normalized scalars.

$\displaystyle {\id{norm-s}}_{\,\mathrm{f}} - {\id{norm-s}}_{\,\mathrm{b}}$ $\displaystyle = { \frac{{s}_{\,\mathrm{f}} - {c}_{\,\mathrm{f}}}{{c}_{\,\mathrm...
...{\,\mathrm{b}} - {c}_{\,\mathrm{f}}}{{c}_{\,\mathrm{f}} - {c}_{\,\mathrm{b}}} }$    
  $\displaystyle = \frac{{s}_{\,\mathrm{f}} - {s}_{\,\mathrm{b}}}{{c}_{\,\mathrm{f}} - {c}_{\,\mathrm{b}}}$ (50)

We know also that, given a linear interpolation of scalar values through space, the distance between two points in space along a viewing vector is proportional to the difference between the scalar values at those points. Therefore,

$\displaystyle \frac{\id{iso-dist}}{d} = \frac{{c}_{\,\mathrm{f}} - {c}_{\,\mathrm{b}}}{{s}_{\,\mathrm{f}} - {s}_{\,\mathrm{b}}}$    

where $ d$, just like in ATFS-VertProg, is the distance between two points with scalar values $ {s}_{\,\mathrm{f}}$ and $ {s}_{\,\mathrm{b}}$. It follows that

$\displaystyle \id{iso-dist} = d \frac{{c}_{\,\mathrm{f}} - {c}_{\,\mathrm{b}}}{{s}_{\,\mathrm{f}} - {s}_{\,\mathrm{b}}}$ (51)

Combining Equation 1.1 and Equation 1.2, we get

$\displaystyle \id{iso-dist} = \frac{d}{{\id{norm-s}}_{\,\mathrm{f}} - {\id{norm-s}}_{\,\mathrm{b}}}$ (52)

which line 6 of ATFS-VertProg clearly computes.

The isosurfaces of the control points are planes within each linearly interpolated tetrahedron. Ideally, we would like to use the clipping hardware of the graphics card to modify the geometry. Unfortunately, the clipping hardware can clip only polygons and the vertex processor cannot generate the extra vertices necessary to clip tetrahedra. Instead, we perform the clipping on each fragment. Consequently, ATFS-FragmentProg is more complicated than the previously defined fragment programs.


\begin{codebox}
\Procname{$\proc{ATFS-FragmentProg}(\vec{d},{\id{norm-s}}_{\,\m...
...ay}(\id{param-{s}_{\,\mathrm{f}}},\id{param-{s}_{\,\mathrm{b}}},d)$\end{codebox}

ATFS-FragmentProg starts the same as the previous fragment programs by determining the face that the viewing ray exits the tetrahedron through (line 1). It then retrieves normalized scalar at the exit point and the distance between ray entry and exit (lines 2 and 3). It follows by retrieving the volume parameters for the two transfer-function control points.9Lines 6 through 15 clip the ray segment.

Figure 1.2: Tetrahedron clipping (reduced to a 2D example). Here I show two example triangles that I clip on a per fragment basis between the two isosurfaces. Six example viewing rays (labeled a-f) are given.
\includegraphics[bb=125 445 490 670,clip=true,width=.95\linewidth]{cell_projection/tet_clipping}

To facilitate our discussion of per fragment tetrahedra clipping, consider Figure 1.2, which shows examples of clipped viewing-ray segments. Some rays, such as ray c, are not clipped at all. Other rays, such as rays a and d, will be completely removed. Still others will be partially clipped such that they enter the front isosurface or exit the back isosurface or both, such as rays e, b, and f, respectively. As I explain the remainder of ATFS-FragmentProg, I will reference the rays in Figure 1.2.

The conditional on line 6 determines whether to clip the ray-tetrahedron intersection entirely. This type of clipping occurs if and only if the ray enters the tetrahedron behind the back isosurface (ray a) or exits the tetrahedron in front of the front isosurface (ray d). Although we could perform this test by comparing the position of intersections along the viewing ray, we can perform the same test by comparing the scalar values at these intersections, which are proportional. Because ATFS-ProjectClippedTet normalized the scalar values at the tetrahedron intersections, this test, like all the other tests, reduces to simply checking whether the normalized scalars are in the range $ [0,1]$. If the test determines to clip the entire ray, ATFS-FragmentProg discards the fragment. That is, it writes nothing into the frame buffer.

The conditional on line 8 determines whether the front isosurface lies within the tetrahedron. This is true if and only if the ray enters the tetrahedron before it intersects the isosurface (and the first test fails). If the test determines to clip the front part of the ray (as in rays e and f), then ATFS-FragmentProg subtracts the distance between the ray entry and the isosurface from the segment length. The volume parameters at the front of the ray are also set to the value at the front isosurface. If the test determines to not clip the front part of the ray (as in rays b and c), then the volume parameters of the two isosurfaces are interpolated to get the scalar value at the surface of the tetrahedron. The conditional on line 12 performs the equivalent operations based on whether the back isosurface is inside the tetrahedron along the ray.

Appendices 1.1 and 1.2 list implementations of the vertex and fragment programs, respectively, required for tetrahedra projection with adaptive transfer function sampling.


next up previous contents index
Next: Synopsis Up: Cell Projection Previous: GPU-CPU Balanced Cell Projection   Contents   Index
Kenneth D Moreland 2004-07-16