Class ObjLightDesc

3DS Max Plug-In SDK

Class ObjLightDesc

See Also: Class LightDesc, Class LightRayTraversal, Class INode, Class Point3, Class Matrix3, Class Ray, Class RendContext, Class ShadeContext, Class RenderInstance.

class ObjLightDesc : public LightDesc

Description:

A light must be able to create one of these objects to give to the renderer. As the renderer is getting ready to render, it will ask for one of these from each of the lights. The Illuminate() method (inherited from LightDesc) is called by the renderer to illuminate a surface point.

There is an ObjLightDesc for every instance of the light. The renderer will ask each light object to produce one of these ObjLightDescs. It will then set this data up in the node's render data (See Class RenderData). For example in 3ds max's volume light implementation of Atmospheric::Update() it goes through its node references to lights and calls GetRenderData(). It then casts this as an ObjLightDesc. This is how a atmosphere effect can get access to these descriptors at render time.

Data Members:

This data will be set up by the default implementation of Update().

public:

LightState ls;

The light state structure. See Structure LightState.

INode *inode;

This parameter is the INode pointer of the instance of the light that created this ObjLightDesc.

BOOL uniformScale;

This indicates if the light's scale is uniform. TRUE if uniform; otherwise FALSE. This saves some steps in the renderer if the scale is uniform.

Point3 lightPos;

The position of the light in camera space.

Matrix3 lightToWorld;

This is effectively the light node's object TM. This matrix will transform points from light space to world space.

Matrix3 worldToLight;

This matrix will transform points from world space to light space. This is the inverse of above.

Matrix3 lightToCam;

This matrix will transform points from light space to camera space. This is updated in UpdateViewDepParams().

Matrix3 camToLight;

This matrix will transform points from camera space to light space. This is updated in UpdateViewDepParams(). For example, the renderer would have points in camera space. To figure out if a point was in shadow it would transform the point from camera space to light space using this matrix. It could then look in the shadow buffer to see if the point was in shadow.

int renderNumber;

This data member is available in release 3.0 and later only.

This is set by the renderer. It is used in RenderInstance::CastsShadowsFrom(). This is a number used by the renderer to identify the lights so it can quickly determine if a given light casts shadows from a given object. It is for use by the renderer.

Methods:

Prototype:

ObjLightDesc(INode *n);

Remarks:

Constructor. The inode data member is initialized to n.

Prototype:

virtual ~ObjLightDesc();

Remarks:

Destructor.

Prototype:

virtual ExclList* GetExclList()

Remarks:

Implemented by the Plug-In.

Retrieves the light's exclusion list.

Return Value:

See Class NameTab.

Default Implementation:

{ return NULL; }

Prototype:

virtual int Update(TimeValue t, const RendContext &rc, RenderGlobalContext *rgc, BOOL shadows, BOOL shadowGeomChanged);

Remarks:

This method is available in release 3.0 and later only.

Implemented by the Plug-In.

This method is called once per render to update the light state for things that depend on the position of objects and lights in world space. A plug-in light could update any data it would need to here. The default implementation is shown below.

Parameters:

TimeValue t

The time of the render.

const RendContext &rc

See Class RendContext.

RenderGlobalContext *rgc

This pointer may be used to retireve information about the global rendering enviornment.

BOOL shadows

TRUE if shadows are turned on (in the render parameters, not the light parameters); otherwise FALSE.

BOOL shadowGeomChanged

This tells the Update procedure that the geometry of the objects that are shadowed by the light has changed (TRUE) or not (FALSE). If it is a shadow buffer, shadowGeomChanged == TRUE means it has to re-render the shadow buffer, shadowGeomChanged == FALSE means it can use the shadow buffer from the previous frame.

Return Value:

The value return should normally be 1. A returned value of 0 means an error has occured (such as out of memory) and the render will be halted.

Default Implementation:

int ObjLightDesc::Update(TimeValue t, const RendContext& rc, RenderGlobalContext *rgc, BOOL shadows, BOOL shadowGeomChanged) {

 if (inode) {

  Interval valid;  

  ObjectState os = inode->EvalWorldState(t);

  assert(os.obj->SuperClassID()==LIGHT_CLASS_ID);

  LightObject* lob = (LightObject *)os.obj;  

  lob->EvalLightState(t, valid, &ls);

  lightToWorld = inode->GetObjTMAfterWSM(t);

  worldToLight = Inverse(lightToWorld);  

  uniformScale = IsUniformScale(lightToWorld);

  affectDiffuse = ls.affectDiffuse;

  affectSpecular = ls.affectSpecular;

  ambientOnly = ls.ambientOnly;

 } else {

  uniformScale = TRUE;

  lightToWorld.IdentityMatrix();

  worldToLight.IdentityMatrix();

  }

 return 1;

 }

Prototype:

virtual void UpdateGlobalLightLevel(Color globLightLevel);

Remarks:

This method is available in release 3.0 and later only.

Implemented by the Plug-In.

This method is called to update the light state that depends on the global light level.

Parameters:

Color globLightLevel

The global light level.

Default Implementation:

{}

Prototype:

virtual int UpdateViewDepParams(const Matrix3& worldToCam);

Remarks:

Implemented by the Plug-In.

This method is called to update the light state that depends on the view matrix. This is used to cache certain computed quantities that are dependent on where you are looking from. In a given scene at a given time, the system may render from several viewpoints. This is because of things like reflection maps and mirrors that need to get rendered. This method is called for each of these different viewpoints.

Parameters:

const Matrix3& worldToCam

The world space to camera space transformation matrix.

Prototype:

virtual Point3 LightPosition();

Remarks:

This method is from LightDesc. Here it provides a default implementation returning the lightPos data member.

Default Implementation:

{ return lightPos; }

Prototype:

virtual void TraverseVolume(ShadeContext& sc, const Ray &ray, int samples, float tStop, float attenStart, float attenEnd, DWORD flags, LightRayTraversal *proc);

Remarks:

Implemented by the Plug-In.

This function traverses a ray through the light volume. This method is implemented by plug-in lights.

Consider how the 3ds max atmospheric effects like the volume lights use this information. For each light the atmospheric effect is bound to, it calls the this method (TraverseVolume()) on the light. The volume light atmospheric effect passes a callback to this method (proc). The light then calls the Step() method of the callback for each partial segment of the ray. Given the illumination on the segment it computes the fog density over that segment. The density may be constant if noise is not turned on, or it may change if noise is turned on. Using the fog density and the illumination it computes the light reflected off the atmosphere for the segment.

Parameters:

ShadeContext& sc

This is the ShadeContext passed into the Shade() method of the Atmospheric effect. The shade context passed in should only be used for state (like are shadows globally disabled). The position, normal, etc. serve no purpose.

const Ray &ray

Defines the world space ray that will be traversed.

int samples

The number of samples to sample along the ray. A reasonable range is from 25-100. This is more or less the suggested number of times the proc->Step() callback will be called. It is not precisely however because the system may take greater or fewer steps than specified as it needs to.

float tStop

This is the end of the ray. This is the point at which the traversal will stop (ray.p+tStop*ray.dir). Note that the traversal can terminate earlier if the callback returns FALSE.

float attenStart

Specifies a percent of the light attenuation distances that should be used for lighting during the traversal. This is used so a light can have an attenuation set to a certain percent, and then have the volume light be attenuated at a different point.

float attenEnd

This specifies the ending percent of the light attenuation distances that should be used for lighting during the traversal.

DWORD flags

There are three ways the shadow maps can be sampled. If none of these flags are set, the shadow map is sampled directly (this is the fastest). One of the following values:

TRAVERSE_LOWFILTSHADOWS

This is a simple filtering where the system samples a point in the shadow map and then some of the neighboring points. This corresponds to 'Medium' in the Volume Light user interface (a value of 0 for flags is 'Low' -- just sampling the shadow map with no filtering at all).

TRAVERSE_HIFILTSHADOWS

This is a higher resolution sampling. This corresponds to 'High' in the Volume Light user interface.

TRAVERSE_USESAMPLESIZE

This produces the highest quality. This corresponds to 'Use Light Sample Range' in the Volume Light user interface. This is like a box filter, but also takes into consideration the position of the point within the pixel to do additional weighting.

LightRayTraversal *proc

A developer derives a class from LightRayTraversal and implements the Step() method. A pointer to it is passed here as the callback object.

Default Implementation:

{}