Miter needs six kinds of information to make a rendering:
- Volume input, image output
- Camera and image information
- Lighting and surface properties
- Kernels used in filtered sampling
- Ray and compositing parameters
- Transfer functions
All of these are communicated to miter with various
command-line options. All the command-line parsing is done by hest.
One very useful capability of hest is its support for "response
files": text files that contain command-line options, especially those
that aren't changing between multiple invocations of the same command.
Response files can have multiple lines, with comments, to help clarify
what information is being communicated. See a
basic miter demo for an
example of response file usage.
1. Volume Input, Image Output
- -i <input volume> : the 3-D nrrd to be
volume rendered
- -o <output image> : the RGBA rendering output
Miter can render 3-D scalar data of any type, from unsigned
char up to double. The output of miter is a four-channel
RGBA image of floats, usually saved as a nrrd. Storing the opacity
channel allows you to composite the rendering over different colors or
patterns. Using floating point ensures that operations like gamma
correction can be done without any visual artifacts.
The teem program overrgb is the best way to convert
the floating point RGBA output of miter into an 8-bit RGB
image suitable for publication or the web.
2. Camera and Image information
The volume being rendered by miter is always centered at the
origin in world-space, inscribed in a bi-unit cube from -1 to 1 along
the X, Y, and Z axes. Any non-isotropic voxels in the volume affects
its aspect ratio and how it is inscribed in this cube, but the world
space around the cube is of course independent from voxel spacings.
Miter uses the same set of command-line options for camera
information as other teem programs. There are unfortunately
many different variables that must be set in order to completely
define the camera. All of them use two letter flags. All
(<X> <Y> <Z>) coordinates
are in world coordinates.
- -fr <X> <Y> <Z> :
From point, or eye point; where camera is located, in world coordinates
- -at <X> <Y> <Z> :
At point; point that camera is nominally looking at.
- -up <X> <Y> <Z> :
Up vector; direction that projects to vertical in the image plane.
- -dn <distance> : distance to the near clipping plane
- -df <distance> : distance to the far clipping plane
- -di <distance> : distance to the image plane.
The "from" point
(-fr) and the "at" point (-at) only define a view origin
and a view direction. The placement of the image plane along this
view direction has to be specified, since it is not always exactly
at the "at" point.
- -ar : The plane distances above are to be at-relative.
Without this option (the default),
the image plane, and the near and far clipping planes are specified
relative to the from "from" point (and they all must be positive).
With this option, they are specified relative to the "at" point (and
they can be positive or negative).
- -rh : right-handed coordinate frame. Without this option
(the default), the V vector points upwards. Since U points
to the right, and W points towards the at point, this means that
(U, V, W) is a left-handed view-space coordinate frame.
With the -rh option, V points downwards, leading to a
right-handed coordinate frame.
- -or : orthogonal projection, instead of perspective projection.
- -ur <Umin> <Umax> : U-range ;
the range of horizontal positions on the
image plane that should be included in the image. The line from "from" to
"at" hits the image plane at U == 0.
- -vr <Umin> <Umax> : V-range ;
the range of vertical positions on the
image plane that should be included in the image. The line from "from" to
"at" hits the image plane at V == 0.
- -is <Usize> <Vsize> : Image size
in integers; the resolution of the image to render.
Hest's "response files" come in especially handy with dealing
with the many camera parameters.
3. Lighting and surface properties
For now, miter supports exactly one light, and it is always
white. All you can control is its direction, or rather, its
"location", which is actually extended out to infinity in order to
create a directional light. Furthermore, you can only specify the
light location in view-space, not world-space. This is done
with the "-ld" option:
- -ld <X> <Y> <Z> :
Light "position" in view space.
Miter supports the Phong lighting model, which gives
you a few parameters to vary:
- -am
<R_{am}>
<G_{am}>
<B_{am}> : Ambient light color.
- -ads
<k_{a}>
<k_{d}>
<k_{s}> : Coefficients of ambient,
diffuse, and specular contributions
- -sp <power> : Specular power
Except for specular power ("-sp"), all these numbers are
intended to vary from 0.0 to 1.0 (but you can set them to whatever you
want). For the sake of simplicity, the k_{a}, k_{d},
k_{s} values do not vary with the red, green, and blue
channels. The idea is that the transfer function assigns an intrinsic
material color, which in visualization contexts is apt to vary across
the surface. The Phong shading parameters determine the surface
appearance, and they are less apt to vary over the surface.
4. Kernels used in filtered sampling
The benefit of using gage for all volume measurements is that
you can get very high quality filtered sampling of the volume.
Gage uses seperable convolution of the original data values
with various continuous kernels in order to measure the values and
derivatives that are needed for the transfer function domain
variables, and for shading. Nothing is pre-computed- all quantities
are computed de novo at each sample point along the ray.
For all this to work, you have to choose a set of kernels to use
for the convolution based measurements. Signal processing tells us
that the choice of kernel can have a big effect on the quality of
the resulting measurements, so some prior knowledge on your part
is assumed here. The kernels used here come from nrrd:
- -k00 <kernel specification> :
The kernel used to reconstruct or interpolate the scalar data values
that comprise the dataset.
- -k11 <kernel specification> :
The kernel used to measure first derivatives, used for finding the
gradient direction for shading, and the gradient magnitude for
transfer functions. Often, this is the first derivative of a reconstruction
or interpolation kernel.
- -k22 <kernel specification> :
The kernel used to measure second derivatives.
Often, this is the second derivative of a reconstruction
or interpolation kernel.
The kernel specifications is of the same form as used for
unu resample, and
many different kernels are possible. However, this combination of
kernels is quite useful:
-k00 cubic:0,0.5 -k11 cubicd:1,0 -k22 cubicdd:1,0
The "cubic" kernels are the BC-family of cubics described
by Mitchell and Netravali. "-k00 cubic:0,0.5" specifies
that the Catmull-Rom kernel be used for interpolating data values.
"-k11 cubicd:1,0" specifies that the first derivative of
the B-spline kernel be used for measuring first derivatives, and
similarly "-k22 cubicdd:1,0" says that the second derivative
of the B-spline kernel should be used for measuring second derivatives.
Even if the transfer function does not require any second derivative
information, there is no harm in specifying it.
5. Ray and compositing parameters
Because this is a ray-casting volume renderer, you need to set parameters
describing the sampling along the ray and the compositing of those samples.
- -step <step size> : Sampling step size along the
rays, in world space. This is going to be a small number, considering
that the whole volume fits in the [-1,1]^{3} cube at the origin.
If you want to set a particular sampling rate relative to the voxel
size, that's up to you. This is the most important knob in controlling the
trade-off between quality and rendering speed.
- -ref <reference step> : mite is
smart about modifying the opacity of the samples to compensate for
changes in step size. That is, halving an already small step size
should result in a rendering of comparable appearance. The mathematics
here rely on some step size as being the reference (for which there is
no opacity correction), and that is given by this option.
- -nt <# threads> : Thanks to hoover,
miter is multi-threaded, although the load-balancing is a little
dumb at the moment. This is how you specify the number of threads.
If your teem wasn't built with pthreads enabled, then setting
this has no effect; only one thread is used.
- -n1 <near 1.0> : An opacity value close
enough to 1.0, so that if a ray has this opacity, it is terminated
early.
6. Transfer functions
Last but not least, the transfer function has to be specified in order
to make a volume rendering. Mite uses seperable transfer
functions of arbitrarily high dimension. That is, you give
mite a list of transfer functions (however many you want), each
of which specifies some number of optical properties as a function of
some number of locally measured data properties:
- -txf
<function 0>
<function 1>
<function 2> ...
Mite will use
the multiplicative product of all those transfer functions in the
rendering. In practice, the dimension of the individual transfer
functions is at most two. One current limitation is that the
individual transfer functions ware only lookup tables: not even linear
interpolation is supported.
As one might guess, Nrrds are used to represent transfer functions.
There are some specific conventions for how the domain and range
of the transfer function are encoded in the nrrd; these are described
here.
The first axis in the nrrd always encodes the range of the
transfer function. Whether the range of the transfer function is a
single scalar (such as opacity), or a list of scalars (such as RGB
color), the first axis of the nrrd is reserved for describing the
transfer function range. Thus, the dimension of the nrrd is always
one greater than the dimension of the transfer function. A transfer
function which assigns opacity as a function of one quantity (data
value) is a one-dimensional transfer function, but it is represented
with a two-dimensional nrrd, for which the size of the first axis
(axis 0) is 1. The quantities in the range of the transfer
function are specified in the label of axis zero, according to
a cryptic set of single-letter codes:
- "A" : opacity
- "R" : red
- "G" : green
- "B" : blue
- "E" : emissivity
- "a" : phong ambient coefficient
- "d" : phong diffuse coefficient
- "s" : phong specular coefficient
- "p" : phong specular power
The number of samples along axis zero has to exactly match the
number of characters in the axis zero label. For transfer functions
which assign only opacity, the axis zero label will be "A", and the
number of samples along axis zero will be one.
The remaining dimensions of the nrrd give the domain of the
transfer function, one dimension per transfer function domain
variable. Two pieces of information need to be set along an axis in
order for mite to understand it as a transfer function domain
variable. First, the axis min and axis max fields have
to be set to the minimum and maximum value of the domain variable
that is handled by the lookup table. Measured values outside this
range are clamped to the range.
Second, the axis label identifies which quantity is used for that axis
of the transfer function. Mite will measure this quantity,
clamp it to the interval of domain values given by the axis min and
max, and then perform the lookup into the transfer function table.
The domain variable quantities are essentially every scalar that gage
knows how to measure in a scalar field, combined with some other
numbers that mite computes for you along each ray.
- "gage(v)" : data value
- "gage(gm)" : gradient magnitude
- "gage(l)" : Laplacian
- "gage(2d)" : 2nd directional derivative along gradient direction
- "gage(k1)" : 1st principle curvature
- "gage(k2)" : 2nd principle curvature
- "gage(cv)" : "curvedness" (total curvature): L2 norm of K1, K2
- "gage(st)" : (K1+K2)/Curvedness
- "gage(si)" : Koenderink's curvature shape index
- "gage(mc)" : Mean curvature
- "gage(gc)" : Gaussian curvature
- "gage(fc)" : Flowline curvature
- "Xw" : X position, world space
- "Xi" : X position, index space
- "Yw" : Y position, world space
- "Yi" : Y position, index space
- "Zw" : Z position, world space
- "Zi" : Z position, index space
- "Tw" : position along ray (world space)
- "Ti" : ray index, ray sample number
- "NdotV" : surface normal dotted with view vector
(which points towards eye)
- "NdotL" : surface normal dotted with light vector
(which points towards light location)
- "GTdotV" : normal curvature in view direction
For example, a rendering of unsigned 8-bit data might use a single
transfer function, giving opacity as a function of data value.
The two-dimensional nrrd used for this has an axis[0] label of "A".
On axis[1], the min and max are probably 0 and 255 respectively,
and the axis[1] label is "gage(v)".