LayoutTool MasterHandler Classes Table of Contents


Availability  LightWave® 9.5
Component  Layout
Header  lwlight.h

Light handlers implement different types of light. Before LightWave® 9.5 only a fixed set of built-in light types were available. With version 9.5 the light calculations have been moved to a plugin API, enabling an unlimited range of light types to be added.

Light plugins provide illumination in a scene. Light plugins are not concerned with how this illumination interacts with a surface to create shading (that is the role of shader handlers). To enforce the seperation between lighting and shading, light handlers are provided with only minimal surface and mesh information. What mesh information is provided is meant for optimization purposes.

Different parts of the rendering and Layout preview system have different requirements for light evaluation. The light API therefore contains several light evaluation functions, each specialized for the various areas. Some are optional, in which case the light does not support that type of rendering, or a fallback evaluation method is used (which may slow down rendering, or produce inaccurate results).

There are four light evaluation functions that a light plugin can implement:

Determines the lighting at a point in space. Used for surface shading.
Generates particles of light originating at the light, shooting into the scene. This is used for caustics.
Gets illumination samples along a ray segment. For use with volumetric lighting.
Returns an array of standard lights which are used as an approximation of the light type for Layout preview rendering.

Light evaluation generates illumination information in the form of one or more rays that illuminate a point in space. These rays can originate from anywhere, and need not be tied to the position of the light item. This allows a single light to create complex lighting effects.

Light handlers can override several parts of the lighting and shading pipeline. Reasons for doing this include optimization, providing the user with controls beyond that provided natively, and removal of options which do not apply to the light type. Handlers can opt to do their own occlusion and volumetric shadow calculations, and apply their own light falloff instead of the native falloff calculations.

As lights are evaluated during rendering, light plugins must be aware of multithreading. Light evaluations associated with rendering are supplied with a pre-allocated array to fill in, rather than having to manage per-thread illumination arrays themselves. For speed, light plugins should avoid using write locks or critical sections in the evaluation functions. The newFrame callback can be used to do pre-computation at the start of each render frame.

Light plugins can also be evaluated from other plugins through the light evaluation global. Evaluating a plugin from mulitple clients at the same time can cause problems if each client expects the plugin to be in a different state (for example, at different frame numbers). To prevent such problems each light evaluator is given a copy of the light plugin instance. It is therefore important that the plugin implements the copy instance function.

Handler Activation Function

   XCALL_( int ) MyLight( int version, GlobalFunc *global,
      LWLightHandler *local, void *serverData );
The local argument to a LightHandler activation function is an LWLightHandler.
   typedef struct st_LWLightHandler
      LWInstanceFuncs* inst;
      LWItemFuncs* item;
      LWRenderFuncs* rend;
      unsigned int (*flags)      (LWInstance);
      LWError      (*newFrame)   (LWInstance, const LWFrameInfo* frameinfo,
                                  unsigned int* maxilluminations,
                                  const LWLightAccess* lightaccess);
      int          (*evaluate)   (LWInstance, const LWDVector spot, double fractime,
                                  LWIllumination illumination[],
                                  const LWLightAccess* lightaccess);
      unsigned int (*getPhotons) (LWInstance, unsigned int maxphotons, LWPhoton photons[],
                                  const LWLightAccess* lightaccess);
      unsigned int (*getRayIlluminations) (LWInstance, LWDVector raystart, LWDVector raydir,
                                           double farclip, unsigned int maxrayilluminations,
                                           LWRayIllumination rayilluminations[],
                                           const LWLightAccess* lightaccess);
      const LWPreviewLight* (*preview)    (LWInstance);
   } LWLightHandler;
The first three members of this structure are the standard handler functions. The context argument to the inst->create function is the LWItemID of the associated light item.
flags = flags( instance )
Returns bit flags combined using bitwise-or. Currently defined flags are:
The light does not support photon generation (for example, caustics).
The light does not support ray illumination (for example, volumetric lights).
Returned illumination already includes the effects of occlusion shadowing.
Returned illumination already includes the effects of volumetric shadowing.
Do not show standard falloff gadgets, and do not apply falloff.
Show the standard falloff gadgets, but do not apply falloff.
The NO_FALLOFF and SHOW_FALLOFF flags can be used by light plugins to override the standard falloff calculations applied by the renderer. At most one of these two flags can be set.

result = newFrame( instance, frameinfo, maxilluminations, lightaccess )
This is called whenever a new set of evaluations is started, usually at the start of a frame render. This is a good place to do some pre-computation. The light access structure is explained below. The frameinfo structure is the same as that used by camera plugins. The plugin fills in maxilluminations with the largest number of illuminations it intends to fill in in the evaluation functions. As this is used to allocate the illumination array, the value should be a tight upper bound (if not exact). Returns a pointer to an error string of something went wrong, or NULL if all is well.

result = evaluate( instance, spot, fractime, illumination, lightaccess )
Given a position spot in space and a fractional time into the frame, compute the illumination by the light. The illumination is returned by filling in the supplied illumination array. The plugin must fill in no more than the maximum number of illuminations it returned in newFrame(). It can however fill in fewer entries, or even none. The actual number is allowed to vary with each call (for example, for some sort of adaptive illumination).
   typedef struct st_LWIllumination {
      LWDVector color;
      double intensity;
      LWDVector direction;
      double distance;
      LWDVector shadowAttenuation;
   } LWIllumination;
color, intensity
The color and intensity of the sample. Do not include the intensity in the color. The renderer will combine the color and intensity. The renderer will also take care of applying the standard light color and intensity and, unless set otherwise through the NO_FALLOFF or SHOW_FALLOFF flags, the falloff. For a light which just uses the standard color, intensity, and falloff settings, the color would be set to white and the intensity to 1.
The direction from which the illumination is coming, in world coordinates. It must be normalized.
The distance between the spot being illuminated, and the source of the illumination. The source need not be the position of the light item. This is used by the renderer to apply falloff and occlusion, if needed. A value of DBL_MAX indicates the source is infinitely far away.
Degree by which shadows attenuate the illumination. Note that each color channel can have its own attenuation.

The supplied time value is a fraction between 0 and 1 that ranges over the time duration of the frame (which can be retrieved from the frameinfo structure supplied to newFrame()). 0 means the start time of the frame, while 1 means the time at the end of the duration of the frame (which may be different than that implied by the current frames per second setting, as it includes the effects of fields and motion blur length). There is no defined ordering to the time values that will be given. It is recommended that the handler pre-compute any animation of settings in newFrame() and uses the fractime parameter to interpolate.
The return value of the function is the number of entries filled in by the evaluation, and must be between zero and maxilluminations set by the newFrame() callback.

result = getPhotons( instance, maxphotons, photons, lightaccess )
Called to generate a number of photons from the light. This is used for caustics, which traces photons through the scene by shooting them from the light source. Each photon has a color, intensity, starting position and direction in world space.
   typedef struct st_LWPhoton {
      LWDVector color;
      double intensity;
      LWDVector direction;
      LWDVector worldPos;
   } LWPhoton;
The light plugin fills in the photon information in the photons array. Up to maxphotons photons can be stored in the array. This number is not related to the maxilluminations value set by newFrame().
The functions returns the number of photons filled in, which must be a number between zero and maxphotons.

result = getRayIlluminations( instance, raystart, raydir, farclip,
                              maxrayilluminations, rayilluminations, lightaccess )
Used to sample the illumination of a light along an arbitrary ray. This is intended to be used for volumetric lights. Support for this function is not yet implemented.

previewlights = preview( instance )
In order to preview a light in Layout, the plugin can provide an array of preview light descriptions. Each preview light is a standard OpenGL light type:
The array must be terminated by a preview light type of LWPREVIEWLIGHT_END. The array contains LWPreviewLight structures. Not all the fields in the structure are used for all preview light types.
   typedef struct st_LWPreviewLight {
      int previewtype;

      LWDVector worldPos;
      LWDVector toWorld[3];

      LWDVector color;
      double intensity;

      double range;
      int falloff;

      double coneAngle;
      double coneEdge;
   } LWPreviewLight;
The preview light type. The array must be terminated with a LWPREVIEWLIGHT_END type.
The world position of the light. Only point and spot lights have a position. Ignored for other types.
The X, Y, and Z axes of the light in world coordinates. The distant and spot lights require only the Z axis. The ambient and point lights have no directional component, so this field is ignored completely for those.
color, intensity
The color and intensity of the light.
range, falloff
Falloff settings for point and spot lights. The falloff is one of the LWLFALL_* values. See the Light Info global on how range and falloff are used.
coneAngle, coneEdge
Used only for the spot preview light type, these give the radius and soft edge angles of the spot in radians.

The return value can be NULL, in which case no preview lights are used.

Interface Activation Function

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

This is the standard interface activation for handlers. XPanels are inserted at the bottom of the Basic tab in the Light Properties panel.

Light Access

The access structure information that may be useful for computing the light.

   typedef struct st_LWLightAccess {
      LWItemID lightID;

      LWDVector worldPos;

      LWDVector toWorld[3];
      LWDVector toLight[3];

      unsigned int maxIlluminations;

      LWRayCastFunc*      rayCast;
      RandomFloatData     randomData;
      LWRandomFloatFunc*  randomFloat;

      unsigned int bounces;
      unsigned int flags;

      LWDVector surfaceNormal;

   } LWLightAccess;
The ItemID of the light that the LightHandler plugin is be applied to.
The position of the light item in world coordinates.
Right, Up and Forward directions of the light in world coordinates.
Inverse of toWorld[3] .
The maximum number of illumination samples the plugin set in newFrame().
Raytracing function available to light plugins for determining occlusion and distance to mesh surfaces. Note that using other raytracing functions which do light evaluations potentially create an infinite recursion situation.
A random number generator which produces consistent results across frames. Returns values in the interval (0, 1).
The number of times the viewing ray has branched, or bounced, before evaluating the light.
A combination of zero or more of:
Set when the light is being evaluated for a sampling ray, for example for soft reflections. Such cases can generally use a lower light quality, resulting in significant time savings.
The light is being evaluated for a point on a mesh surface. This indicates the existence of a surface normal (see below).
The light evaluation is part of a preprocessing step, typically radiosity preprocessing. As with the LWLF_SAMPLEDRAY flag the plugin can use this to evaluate quicker at a lower quality.
If the LWLF_HAVESURFACE flag is set (see above), then the normal of the surface is supplied in this field. Otherwise the values are undefined.