ObjReplacementHandler PolygonHandler Classes Table of Contents


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.

A pixel filter may be called to process pixels in any order. Do not assume that the evaluation of pixels will occur sequentially. Pixel filters should also be written to be thread-safe, as they may be called from multiple render threads.

Handler Activation Function

   XCALL_( int ) MyPixelFilter( int 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, and the LWPFF_EVERYPIXEL flag indicates that the filter should be evaluated for every pixel, despite adaptive sampling settings. The LWPFF_BEFOREVOLUME flag causes the pixel filter to be evaluated before the first volumetric evaluation for the pixel. The LWPFF_MULTITHREADED indicates that the pixel filter is thread safe and can be called from multiple threads at the same time.
Interface Activation Function
   XCALL_( int ) MyInterface( int 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;
      LWRayTraceModeFunc      *rayTraceMode;
      LWIlluminateSampleFunc  *illuminateSample;
      RandomFloatData    randomData;
      LWRandomFloatFunc  *randomFloat;
      LWIlluminateNormalFunc *illuminateNormal;
      LWIlluminateSampleNormalFunc *illuminateSampleNormal;
   } 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 a type of LWBUF_RAW_RED, for example, the number can be up to 3 to get RAW_RED, RAW_GREEN and RAW_BLUE, and for LWBUF_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.

The function generates a random number on [>0, <1] interval.

Rendering Functions

lit = illuminate( lightID, position, direction, color )
len = rayTrace( position, direction, color )
len = rayCast( position, direction )
len = rayShade( position, direction, shaderAccess )
len = rayTraceMode( position, direction, color, eta, rtmode )
lit = illuminateSample( lightID, position, direction, sampler, data )
lit = illuminateNormal( lightID, position, direction, normal, color )
lit = illuminateSampleNormal( lightID, position, direction, normal, sampler, data )
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.


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®.