PixelFilterHandler
PixelFilterInterface
Availability LightWave 6.0 | Component Layout, Modeler | Header lwfilter.h
Pixel filters apply image processing effects to individual pixels in the rendered image.
Pixel filters look like image filters at first glance, but they differ in several significant ways. Pixel filters can modify any of the buffers, not just the red, green, blue and alpha values, and they have access to the raytracing functions. They're applied during rendering, before antialiasing and motion blur, so their effects are automatically accumulated by Layout for antialiasing and motion blur purposes.
Unlike image filters, which have access to the entire image and are called once per frame, pixel filters only evaluate, and only have access to, a single pixel sample at a time, and they can be called multiple times per pixel during the rendering of a frame.
Handler Activation Function
XCALL_( int ) MyPixelFilter( long version, GlobalFunc *global, LWPixelFilterHandler *local, void *serverData );
The local
argument to a pixel filter's activation function is an
LWPixelFilterHandler.
typedef struct st_LWPixelFilterHandler { LWInstanceFuncs *inst; LWItemFuncs *item; LWRenderFuncs *rend; void (*evaluate) (LWInstance, const LWPixelAccess *); unsigned int (*flags) (LWInstance); } LWPixelFilterHandler;
The first three members of this structure are the standard handler functions. In addition to these, a pixel filter provides an evaluation function and a flags function.
The context
argument to the inst->create
function is a pointer to
an integer containing context flags. If the LWFCF_PREPROCESS
flag is set, the
instance is being created for an image other than the rendered output, and buffers other
than the RGBA of the image won't be available.
A pixel filter can be activated by both Layout and Modeler. When activated by Modeler,
the LWItemFuncs pointer in the local data is NULL. Be sure to test for this before filling
in the useItems
and changeID
fields. Note too that if your pixel filter
relies on Layout-only globals, those won't be available when Modeler calls your callbacks.
evaluate( instance, access )
- This is where the pixel filter does its work. For each frame, the filter is given access to the red, green, blue and alpha values of each pixel sample, along with any other pixel data requested by the flags function. The access structure, described below, provides pixel information and functions for examining the buffers and writing new values.
flags( instance )
- Returns an int that tells the renderer which buffers the pixel filter will examine
and/or modify and whether the evaluation function will call one of the raytracing
functions in the access structure. The return value contains bitfields combined using
bitwise-or. See the image filter page for a list of the
buffer codes. In addition to these, the
LWPFF_RAYTRACE
flag indicates that the evaluation function will call the raytracing functions.
Interface Activation Function
XCALL_( int ) MyInterface( long version, GlobalFunc *global, LWInterface *local, void *serverData );
This is the standard interface activation for handlers.
Pixel Access
The pixel access structure passed to the evaluation function contains the pixel
coordinates for the sample, functions for getting and setting pixel values, and the
raytracing functions. Because the sampling of the output image is adaptive, pixel
positions may be evaluated in any order, multiple times, or not at all. The evaluation
function must call setRGBA
for every pixel it evaluates, even if the filter
doesn't modify the pixel.
typedef struct st_LWPixelAccess { double sx, sy; void (*getVal) (int type, int num, float *); void (*setRGBA) (const float[4]); void (*setVal) (int type, int num, float *); LWIlluminateFunc *illuminate; LWRayTraceFunc *rayTrace; LWRayCastFunc *rayCast; LWRayShadeFunc *rayShade; } LWPixelAccess;
sx, sy
- Image coordinates of the sample, in pixel units. These will often contain fractional values.
getVal( type, buflen, buf )
- Get a pixel value from one of the buffers. If the buffer type is invalid or a type not
requested by the flags function, the pixel value returned in
buf
is undefined. See the image filter page for the list of buffer types.buflen
is the number of contiguous values to return. For most buffers, this number will be 1, but the RGB buffers can be retrieved all at once. With atype
ofLWBUF_RAW_RED
, for example, the number can be up to 3 to getRAW_RED
,RAW_GREEN
andRAW_BLUE
, and forLWBUF_RED
it can be up to 4, for the RGBA values. setRGBA( rgba )
- The RGBA (red, green, blue and alpha) output of the pixel filter. This must be called even if the filter doesn't modify the values.
setVal( type, buflen, buf )
- Write a value to one of the buffers.
lit = illuminate( lightID, position, direction, color )
len = rayTrace( position, direction, color )
len = rayCast( position, direction )
len = rayShade( position, direction, shaderAccess )- These functions trace rays into the scene. See the raytracing
functions page for details. You can only use these if the return value of your flags
function includes the
LWPFF_RAYTRACE
flag.
Example
The zcomp sample includes a pixel filter that
composites the render with an image sequence using the LWBUF_DEPTH
buffer. zcomp
compares the depth at each pixel with the corresponding depth in the image to be
composited, and substitutes the image pixel if it's nearer in z order to the camera.
The mandfilt sample turns LightWave into a Mandelbrot set renderer. Unlike most real pixel filters, it simply overwrites the pixel values with its own output, so it should be run in an empty scene. But it does demonstrate how pixel filter output is antialiased and adaptively sampled by LightWave.