VolumetricHandler
VolumetricInterface

Availability LightWave 6.0 | Component Layout | Header lwvolume.h

Volumetric handlers model the attenuation and scattering of light in gases, differences in density in 3D medical imaging data, or the shapes of surfaces too complex to model explicitly with geometry. They do this by participating in LightWave's raytracing mechanism.

For each ray fired into the scene, the volumetric handler calculates a color and opacity for one or more samples. It hands each sample back to LightWave, which integrates all of the samples from all of the volumetrics to produce the final color seen from the source of the ray.

A sample represents a segment of the ray over which the color and opacity are constant.  Consider a simple cloud pierced by a ray. The handler that draws the cloud isn't interested in the parts of the ray that are outside it, so it creates no samples there. In the simplest case, it may create a single sample that begins at the point where the ray enters the cloud and extends as far as the ray remains inside. If the cloud is somewhat transparent, the color might be a linear combination of the cloud color and the backdrop color, and the opacity will be somewhat less than 1.0.

Handler Activation Function

   XCALL_( int ) MyVolumetric( long version, GlobalFunc *global,
      LWVolumetricHandler *local, void *serverData );

The local argument to a volumetric handler's activation function is an LWVolumetricHandler.

   typedef struct st_LWVolumetricHandler {
      LWInstanceFuncs *inst;
      LWItemFuncs     *item;
      LWRenderFuncs   *rend;
      double          (*evaluate) (LWInstance, LWVolumeAccess *);
      unsigned int    (*flags)    (LWInstance);
   } LWVolumetricHandler;

The first three members of this structure point to the standard handler functions. In addition to these, a volumetric handler provides an evaluation function and a flags function.

d = evaluate( instance, access )
Called for each ray fired into the scene. The evaluation function adds zero or more samples to the ray, based on the information in the access structure, described below.
f = flags( instance )
Returns an int that tells the renderer which effects the handler supplies. The return value contains bitfields combined using bitwise-or.
LWVOLF_SHADOWS
The evaluation function can be called for shadow rays.
LWVOLF_REFLECTIONS
Can be evaluated for reflection rays.
LWVOLF_REFRACTIONS
Can be evaluated for refraction rays.

Interface Activation Function

   XCALL_( int ) MyInterface( long version, GlobalFunc *global,
      LWInterface *local, void *serverData );

This is the standard interface activation for handlers.

Volumetric Access

This is the structure passed to the handler's evaluation function.

   typedef struct st_LWVolumeAccess {
      void             *ray;
      int               flags;
      LWItemID          source;
      double            o[3], dir[3];
      double            rayColor[3];
      double            farClip, nearClip;
      double            oDist, frustum;
      void             (*addSample) (void *ray, LWVolumeSample *smp);
      double           (*getOpacity)(void *ray, double dist,
                                       double opa[3]);
      LWIlluminateFunc *illuminate;
      LWRayTraceFunc   *rayTrace;
      LWRayCastFunc    *rayCast;
      LWRayShadeFunc   *rayShade;
   } LWVolumeAccess;
ray
An opaque pointer to LightWave's representation of the ray. Pass this as the first argument to the addSample and getOpacity functions.
flags
Evaluation flags. Some of these allow the evaluation function to streamline its calculations.
LWVEF_OPACITY
Calculate an opacity value for each sample. When this flag is absent, the opacity calculation can be omitted.
LWVEF_COLOR
Calculate a color for each sample.
LWVEF_RAYTRACE
If this flag is absent, the evaluation function is being called during the volumetric pass that occurs before pixel filtering but after normal rendering. Otherwise the evaluation function is being called during "regular" raytracing (reflection, refraction or shadow rays, for example).
source
The item from which the ray originated. This can be a light (for shadow rays), a camera, or LWITEM_NULL for other sources.
o, dir
The origin and direction of the ray. The origin is the position of the source item or of a spot on the surface of the source object.
far, near
Far and near clipping distances. These are distances along the ray measured from the origin o along the direction dir. All sample segments will normally fall between these two.
rayColor
The color seen from the origin of the ray, before volumetric effects are applied.
oDist
Distance from the origin o to the true start of the viewing path. This is non-zero for reflection and refraction rays. If the origin o is a spot on the surface of an object, oDist is the distance from that spot to the camera. This is good to know if your calculations will be based on the length of the path to the viewer (the camera) and not just on the length of the ray fired from the spot on the object.
frustum
Pixel frustum, equal to 2 * tan(0.5 * hfov)/w, where hfov is the horizontal field of view and w is the width of the rendered image in pixels. The frustum is a measure of the size of a pixel relative to the ray. (It's the actual size of the pixel at a distance of 1.0.) This quantity plays a role in calculating sample size, or stride, during raymarching. A typical calculation of the stride might look like
increment = scale_factor * frustum;
stride = dist * increment;
addSample( ray, sample )
Add a new volume sample to the ray. This is how volumetric handlers submit their contributions to the integration of opacity and color along the ray. The sample structure is described below.
opacity = getOpacity( ray, dist, opa )
Returns the currently calculated opacity (vector and scalar) at the specified distance.
 
lit = illuminate( lightID, position, direction, color )
len = rayTrace( position, direction, color )
len = rayCast( position, direction )
len = rayShade( position, direction, shaderAccess )
See the raytracing functions page for a description of these.

Volume Sample

A volume sample is a single ray segment with a uniform color and opacity. The distance and stride define the position and size of the sample, and the opacity and color are given as color vectors. By the way, you can create surface samples by setting stride to 0 and dist to 0.9999 * farClip.

   typedef struct st_LWVolumeSample {
      double  dist;
      double  stride;
      double  opacity[3];
      double  color[3];
   } LWVolumeSample;
dist
The starting point of the sample expressed as a distance from the origin of the ray. This should be greater than or equal to nearClip.
stride
The length of the sample. dist + stride should be less than or equal to farClip.
opacity
The red, green and blue components of the opacity of this sample.
color
The color at this sample.

Example

The atmosphere sample is a straightforward implementation of some of the volumetric techniques discussed in chapter 14 (K. Musgrave, L. Gritz, S. Worley) of Texturing and Modeling, 2nd ed., Academic Press, 1998. It includes both a fast analytical solution that creates a single sample and a more refined solution that uses raymarching and multiple samples per ray.