pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
NAME
pfNewLSource, pfGetLSourceClassType, pfLSourceAmbient,
pfGetLSourceAmbient, pfLSourceColor, pfGetLSourceColor, pfLSourceAtten,
pfGetLSourceAtten, pfSpotLSourceDir, pfGetSpotLSourceDir,
pfSpotLSourceCone, pfGetSpotLSourceCone, pfLSourcePos, pfGetLSourcePos,
pfLSourceOn, pfLSourceOff, pfIsLSourceOn, pfLSourceMode,
pfGetLSourceMode, pfLSourceVal, pfGetLSourceVal, pfLSourceAttr,
pfGetLSourceAttr - Create pfLightSource, specify pfLightSource
properties.
FUNCTION SPECIFICATION
#include <Performer/pf.h>
pfLightSource * pfNewLSource(void);
pfType * pfGetLSourceClassType(void);
void pfLSourceAmbient(pfLightSource* lsource, float r,
float g, float b);
void pfGetLSourceAmbient(pfLightSource* lsource, float* r,
float* g, float* b);
void pfLSourceColor(pfLightSource* lsource, int which,
float r, float g, float b);
void pfGetLSourceColor(pfLightSource* lsource, int which,
float* r, float* g, float* b);
void pfLSourceAtten(pfLightSource* light, float constant,
float linear, float quadratic);
void pfGetLSourceAtten(pfLightSource* light,
float *constant, float *linear, float *quadratic);
void pfSpotLSourceDir(pfLightSource* lsource, float x,
float y, float z);
void pfGetSpotLSourceDir(pfLightSource* lsource, float* x,
float* y, float* z);
void pfSpotLSourceCone(pfLightSource* lsource, float f1,
float f2);
void pfGetSpotLSourceCone(pfLightSource* lsource, float* f1,
float* f2);
void pfLSourcePos(pfLightSource* lsource, float x, float y,
float z, float w);
Page 1
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
void pfGetLSourcePos(pfLightSource* lsource, float* x,
float* y, float* z, float* w);
void pfLSourceOn(pfLightSource* lsource);
void pfLSourceOff(pfLightSource* lsource);
int pfIsLSourceOn(pfLightSource* lsource);
void pfLSourceMode(pfLightSource *lsource, int mode,
int val);
int pfGetLSourceMode(const pfLightSource *lsource,
int mode);
void pfLSourceVal(pfLightSource *lsource, int mode,
float val);
float pfGetLSourceVal(const pfLightSource *lsource,
int mode);
void pfLSourceAttr(pfLightSource *lsource, int attr,
void *obj);
void* pfGetLSourceAttr(const pfLightSource *lsource,
int attr);
PARENT CLASS FUNCTIONS
The OpenGL Performer class pfLightSource is derived from the parent class
pfNode, so each of these member functions of class pfNode are also
directly usable with objects of class pfLightSource. Casting an object
of class pfLightSource to an object of class pfNode is taken care of
automatically. This is also true for casts to objects of ancestor
classes of class pfNode.
pfGroup * pfGetParent(const pfNode *node, int i);
int pfGetNumParents(const pfNode *node);
void pfNodeBSphere(pfNode *node, pfSphere *bsph, int mode);
int pfGetNodeBSphere(pfNode *node, pfSphere *bsph);
pfNode* pfClone(pfNode *node, int mode);
pfNode* pfBufferClone(pfNode *node, int mode, pfBuffer *buf);
int pfFlatten(pfNode *node, int mode);
int pfNodeName(pfNode *node, const char *name);
const char * pfGetNodeName(const pfNode *node);
pfNode* pfFindNode(pfNode *node, const char *pathName,
pfType *type);
pfNode* pfLookupNode(const char *name, pfType* type);
int pfNodeIsectSegs(pfNode *node, pfSegSet *segSet,
pfHit **hits[]);
void pfNodeTravMask(pfNode *node, int which, uint mask,
int setMode, int bitOp);
Page 2
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
uint pfGetNodeTravMask(const pfNode *node, int which);
void pfNodeTravFuncs(pfNode* node, int which,
pfNodeTravFuncType pre, pfNodeTravFuncType post);
void pfGetNodeTravFuncs(const pfNode* node, int which,
pfNodeTravFuncType *pre, pfNodeTravFuncType *post);
void pfNodeTravData(pfNode *node, int which, void *data);
void * pfGetNodeTravData(const pfNode *node, int which);
void pfNodeTravMode(pfNode* node, int which, int mode,
int val);
int pfGetNodeTravMode(const pfNode* node, int which,
int mode);
Since the class pfNode is itself derived from the parent class pfObject,
objects of class pfLightSource can also be used with these functions
designed for objects of class pfObject.
void pfUserDataSlot(pfObject *obj, int slot, void *data);
void pfUserData(pfObject *obj, void *data);
void* pfGetUserDataSlot(pfObject *obj, int slot);
void* pfGetUserData(pfObject *obj);
int pfGetNumUserData(pfObject *obj);
int pfGetNamedUserDataSlot(const char *name);
const char* pfGetUserDataSlotName(int slot);
int pfGetNumNamedUserDataSlots(void);
int pfDeleteGLHandle(pfObject *obj);
Since the class pfObject is itself derived from the parent class
pfMemory, objects of class pfLightSource can also be used with these
functions designed for objects of class pfMemory.
pfType * pfGetType(const void *ptr);
int pfIsOfType(const void *ptr, pfType *type);
int pfIsExactType(const void *ptr, pfType *type);
const char * pfGetTypeName(const void *ptr);
int pfRef(void *ptr);
int pfUnref(void *ptr);
int pfUnrefDelete(void *ptr);
int pfUnrefGetRef(void *ptr);
int pfGetRef(const void *ptr);
int pfCopy(void *dst, void *src);
int pfDelete(void *ptr);
int pfIsFluxed(void *ptr);
int pfCompare(const void *ptr1, const void *ptr2);
void pfPrint(const void *ptr, uint which, uint verbose,
FILE *file);
void * pfGetArena(void *ptr);
Page 3
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
PARAMETERS
lsource identifies a pfLightSource.
DESCRIPTION
A pfLightSource is a pfNode which can illuminate geometry in a pfScene.
In addition, pfLightSource supports a technique known as "projected
texturing" which can simulate high quality, real time spotlights and
shadows on certain graphics hardware.
pfNewLSource creates and returns a handle to a pfLightSource. Like other
pfNodes, pfLightSources are always allocated from shared memory and can
be deleted using pfDelete.
pfGetLSourceClassType returns the pfType* for the class pfLightSource.
The pfType* returned by pfGetLSourceClassType is the same as the pfType*
returned by invoking pfGetType on any instance of class pfLightSource.
Because OpenGL Performer allows subclassing of built-in types, when
decisions are made based on the type of an object, it is usually better
to use pfIsOfType to test if an object is of a type derived from a
Performer type rather than to test for strict equality of the pfType*'s.
Most pfLightSource routines are borrowed from pfLight. These routines
have the identical function as the pfLight routines but operate on a
pfLightSource rather than a pfLight. The routine correspondence is listed
in the following table.
pfLightSource routine pfLight routine
__________________________________________
pfLSourceAmbient pfLightAmbient
pfGetLSourceAmbient pfGetLightAmbient
pfLSourceColor pfLightColor
pfLSourceAtten pfLightAtten
pfGetLSourceColor pfGetLightColor
pfLSourcePos pfLightPos
pfGetLSourcePos pfGetLightPos
pfSpotLSourceCone pfSpotLightCone
pfGetSpotLSourceCone pfGetSpotLightCone
pfSpotLSourceDir pfSpotLightDir
pfGetSpotLSourceDir pfGetSpotLightDir
pfLSourceOn pfLightOn
pfLSourceOff pfLightOff
pfIsLSourceOn pfIsLightOn
|
The reader is referred to the pfLight man page for details on the routine
description.
When enabled by pfLSourceOn, a pfLightSource influences all geometry that
is in the same pfScene if it is not culled during the cull traversal.
Its position in the hierarchy does not affect its area of influence. A
pfLightSource is enabled by default and is explicitly disabled with
pfLSourceOff.
Page 4
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
pfLightSources are processed somewhat differently than other nodes. If
the PFCULL_IGNORE_LSOURCES mode is not enabled by pfChanTravMode, the
cull stage will begin with a special traversal of all paths which lead
from the current pfScene to pfLightSources before it traverses the
pfScene geometry. This initial traversal is no different from the
ordinary cull traversal except that the traversal order is path-directed
rather than an in-order traversal. Specifically, all switches (pfSwitch,
pfLOD, pfSequence) and transformations (pfSCS, pfDCS) will affect the
traversal. Note that nodes that lie on paths to pfLightSource nodes will
be traversed multiple times; specifically, any cull or draw callbacks (-
pfNodeTravFuncs) will be invoked multiple times.
pfLightSources are culled to the viewing frustum only if they have been
assigned a non-null bounding volume (pfNodeBSphere). If a pfLightSource
has a null bounding volume (radius < 0) then it is not culled and has
global effect over its pfScene. By default pfLightSources have null
bounding volumes. After the pfLightSource traversal comes the database
traversal which (usually) visually culls the current pfScene and ignores
pfLightSources.
A pfLightSource inherits the current transformation from any pfSCSes and
pfDCSes above it in the hierarchy. This matrix transforms the light
source's position and direction depending on the light's type, i.e.- if
it is a local, infinite, or spotlight.
All hardware lights corresponding to pfLightSources in a pfScene will be
properly configured before the pfChannel's draw callback is invoked (see
pfChanTravFunc). Consequently, all geometry rendered in the pfChannel
draw callback will be illuminated by the pfScene's light sources.
However, any draw callback assigned to the pfLightSource node by
pfNodeTravFuncs will be invoked before the pfChannel draw callback is
invoked so that anything drawn in the node callback will be obscured if
the channel viewport is cleared (see pfClearChan). Example 1: Adding a
pfLightSource to a pfScene.
sun = pfNewLSource();
/* Set slightly yellow color */
pfLSourceColor(sun, PFLT_DIFFUSE, 1.0f, 1.0f, .8f);
/* Set a high ambient level */
pfLSourceColor(sun, PFLT_AMBIENT, .4f, .4f, .3f);
/* Time of day is high noon */
pfLSourcePos(sun, 0.0f, 1.0f, 0.0f, 0.0f);
pfAddChild(scene, sun);
A pfLightSource supports 3 different lighting mechanisms as listed in the
following table:
Page 5
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
Lighting Normals Texture Effects Are Shadows Extra Draw
Method Used Required Per-? Pass(es)
__________________________________________________________________
pfLight Yes No Vertex No None
PROJTEX No Yes Pixel No +(0-1)
SHADOW No Auto Pixel Yes +(0-2)
|
|
|
|
|
The normal use of a pfLightSource is as a pfLight which computes lighting
at geometry vertices, taking into account the surface curvature as
represented by geometry normals. This kind of lighting offers the highest
performance but does not produce per-pixel effects or shadows. Lighting
using projected textures, referred to as PROJTEX, produces high quality
spotlights since the spotlight boundary is computed on a per-pixel,
rather than a per-vertex basis as it is with pfLight. However, PROJTEX
lighting does not take surface normals into account, requires hardware
texture mapping for decent performance, and requires that textured
geometry be rendered twice, once with their normal texture and once with
the projected texture. SHADOW lighting is similar to PROJTEX but adds
shadows at the cost of an additional rendering pass. In this case a
special texture map, called a shadow map, is automatically generated by
the pfLightSource and then projected onto the scene. Typically,
pfLight-type lighting is used in conjunction with PROJTEX or SHADOW so
that lighting is a function of both per-pixel projected texturing and
per-vertex surface curvature.
Two different algorithms are implemented in performer. One for IrisGL,
with shadows only on RE2, unchanged since 2.0 release. One for OpenGL,
with shadows only on IR, introduced in 2.2 release. The main difference
between those 2 algorithms is that the IrisGL algorithm requires an alpha
plane if more than one multipass light is used, the OpenGL algorithm use
only color planes.
The IrisGL algorithm is: - draw a pass will all lights on. Using the
textures in the database - Blend all the PROJTEX and SHADOW in the alpha
plane, using texgen - Multiply the results
Because this algorithm uses alpha, it can only take account of the
intensity of the SHADOW/PROJTEX, and merge all colors together in a first
pass. This is why 2 PROJTEX with different colors will result in 2
PROJTEX with one merged color. The last pass is done at the same time as
the last PROJTEX/SHADOW pass, at no additional cost.
If the database is non texture, the first pass can be done at the same
time as the first PROJTEX/SHADOW pass. So a non textured database, with
one PROJTEX/SHADOW is done in a single pass.
There is no distinction between PROJTEX and SHADOW in the second pass,
all intensities are multiplied together.
The OpenGL algorithm is: - draw a pass with all non PROJTEX/SHADOW
pfLightSources - Additive Blend all the PROJTEX - Multiplicative Blend
all the SHADOW - Draw the scene with its own textures and multiply on
Page 6
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
each RGB component with the previous result There is one more pass with
the OpenGL algorith (the first), if non PROJTEX/SHADOW pfLightSources are
in the Scene.
SHADOW and PROJTEX lighting are separately enabled and disabled with the
PFLS_SHADOW_ENABLE and PFLS_PROJTEX_ENABLE tokens to pfLSourceMode. val
should be either PF_ON or PF_OFF. When either is enabled, pfChannels
rendering the pfLightSource's scene automatically enter "multipass mode"
since multiple renderings of the scene are usually required.
pfChanTravMode with the PFTRAV_MULTIPASS traversal token offers some
control over the multiple renderings of the scene. With IrisGL, The
PFMPASS_GLOBAL_AMBIENT bit indicates that the alpha bitplanes of the
pfChannel's viewport contain the ambient intensity of the scene. Note
that the pfChannel will not clear the viewport alpha to this intensity
but expects it to have already been properly cleared. If using a
pfEarthSky to clear the viewport, you can specify the ambient alpha with
pfESkyColor. Global ambient is not required and does have some extra
cost. It is not particularly useful for PROJTEX lighting since ambient
intensity can be easily incorporated in the projected texture (instead of
black, just use gray outside the spotlight) but is useful for SHADOWS
which otherwise would be completely black. With OpenGL, this bit has no
effect, and the Shadow intensity is given by the PFLS_INTENSITY value of
the light source, 0 is a full dark shadow.
By default, emissive surfaces (including light points) are attenuated by
PROJTEX and SHADOW lighting which is not correct since emissive surfaces
should shine even if in shadow or outside the cone of a projected
spotlight. If a scene has emissive surfaces, set the
PFMPASS_EMISSIVE_PASS bit in the PFTRAV_MULTIPASS mode and the emissive
surfaces will be properly rendered. Note that the emissive rendering pass
is not a full pass - rather it is a pass of only the emissive surfaces.
In situations where the scene is entirely non-textured,
PFMPASS_NONTEX_SCENE can be specified as part of the PFTRAV_MULTIPASS
traversal mode of a pfChannel. In this case a complete rendering pass is
eliminated.
PROJTEX lighting requires that a pfTexture be specified with the
PFLS_PROJ_TEX token to pfLSourceAttr. obj should be an intensity-alpha
(2-component) pfTexture* with identical intensity and alpha components if
using IrisGL. With OpenGL, the alpha component of the projected texture
will modify the transparency of the objects in the scene. If this is not
desired, the alpha component of the texture should be zeroed.
With OpenGL, the textures may also be a full color 4-component texture.
With IrisGL, a color texture can be used if this is the only
pfLightSource in the scene using PROJTEX lighting.
SHADOW lighting does not require a pfTexture, rather one is automatically
created and configured by the pfLightSource. The size of the
texture(shadow) map may be specified with the PFLS_SHADOW_SIZE token to
Page 7
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
pfLSourceVal. val is then the square size of the texture map. The size
of the shadow map greatly influences the quality and performance of
SHADOW lighting. Large shadow map sizes increase quality but decrease
performance. The default shadow map size is 256. SHADOW lighting
requires that the viewport of each pfChannel which renders the
pfLightSource's scene be at least as big as the shadow map. Otherwise,
shadows will be clipped and visual anomalies will occur.
Both SHADOW and PROJTEX lighting require that a pfFrustum be specified
with the PFLS_PROJ_FRUSTUM token to pfLSourceAttr. obj defines the
projection of the texture (shadow) map and should be a nominal, i.e.,
non-transformed pfFrustum*. For SHADOW lighting, the field-of-view and
near and far clipping planes should bracket the scene to be shadowed as
tightly as possible for best results. A sloppy fit of pfFrustum to scene
will result in blocky, poor-quality shadows.
By default, SHADOW lighting requires that the scene be rendered from the
point of view of the pfLightSource to produce a shadow map. By default,
pfChannels automatically do this for each SHADOW pfLightSource in their
scene. However, a new shadow map is only required if the pfLightSource
or objects in the scene change. In the special case where the
pfLightSource and scene are totally static (e.g., the sun illuminating a
sleepy town), the shadow map need not be recomputed. In this case
pfLSourceMode(PFLS_FREEZE_SHADOWS, PF_ON) will disable the automatic
recomputation of the shadow map, increasing performance.
For best results, SHADOW lighting requires that the scene be slightly
displaced in depth when rendering the shadow map. This reduces artifacts
such as "self-shadowing". The PFLS_SHADOW_DISPLACE_SCALE and
PFLS_SHADOW_DISPLACE_OFFSET tokens to pfLSourceVal specify displacement
values. The default values are respectively: for IrisGL 1.0 and 256.0
for OpenGL 1.0 and .0019 but experimentation is required for best results
(both values should be positive).
For pfLightSources which are near the eye, a pfFog can be used to
simulate range-attenuation of the light. Range-attenuation is enabled
with the PFLS_FOG_ENABLE token to pfLSourceMode and by specifying a pfFog
with the PFLS_PROJ_FOG token to pfLSourceAttr. The pfFog color should be
the ambient color of the projected texture. Only a single range-
attenuated projected pfLightSource is supported for a given pfChannel.
With IrisGL A pfLightSource's intensity is set with the PFLS_INTENSITY
token to pfLSourceVal. val simply scales the color(s) of all 3 lighting
types: pfLight, PROJTEX, SHADOW. A scene containing multiple, full-
intensity pfLightSources can be easily saturated so setting pfLightSource
intensities is a simple way to "normalize" lighting within a scene. For
example, when using 3 pfLightSources to illuminate a scene, an intensity
of .33 would be reasonable.
With OpenGL, the PFLS_INTENSITY has effect only for shadows to set the
intensity inside the shadow. The amount of light is given directly by the
PFLT_DIFFUSE value, that is a full RGB triplet, so every light/shadow can
Page 8
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
be colored.
Example 2: Range-attenuated, projected texture lighting for landing light
pfLightSource *spot;
pfTexture *spotTex;
pfFrustum *spotFrust;
pfFog *spotFog;
pfDCS *spotDCS;
pfChannel *chan;
pfEarthSky *esky;
// Create and load 2-component spotlight
spotTex = pfNewTex(arena);
pfLoadTexFile(spotTex, "spot.inta");
// Create and configure projected texture frustum
spotFrust = pfNewFrust(arena);
pfMakeSimpleFrust(spotFrust, 60.0f);
pfFrustNearFar(spotFrust, 1.0f, 100.0f);
// Create and configure range-attenuation fog model
spotFog = pfNewFog(arena);
pfFogColor(spotFog, 0.1f, 0.1f, 0.1f);
pfFogRange(spotFog, 0.0f, 100.0f);
// Create and configure projected texture light source
spot = pfNewLSource();
pfLSourceAttr(spot, PFLS_PROJ_TEX, spotTex);
pfLSourceAttr(spot, PFLS_PROJ_FRUST, spotFrust);
pfLSourceAttr(spot, PFLS_PROJ_FOG, spotFog);
pfLSourceMode(spot, PFLS_PROJTEX_ENABLE, 1);
// Set spotDCS to viewing matrix to move light around with eye
spotDCS = pfNewDCS();
pfAddChild(spotDCS, spot);
pfAddChild(scene, spotDCS);
// Enable emissive pass since scene has emissive surfaces
pfChanTravMode(chan, PFTRAV_MULTIPASS, PFMPASS_EMISSIVE_PASS);
Example 3: Multiple, shadow-casting, colored pfLightSources
pfLightSource *shad0, *shad1;
pfDCS *shadDCS0, *shadDCS1;
pfFrustum *shadFrust;
pfChannel *chan;
pfEarthSky *esky;
Page 9
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
// Create and configure shadow frustum
shadFrust = pfNewFrust(arena);
pfMakeSimpleFrust(shadFrust, 60.0f);
pfFrustNearFar(shadFrust, 1.0f, 100.0f);
// Create and configure shadow casting light sources
shad0 = pfNewLSource();
pfLSourceMode(shad0, PFLS_SHADOW_ENABLE, 1);
pfLSourceAttr(shad0, PFLS_PROJ_FRUST, shadFrust);
pfLSourceColor(shad0, PFLT_DIFFUSE, 1.0f, 0.0f, 0.0f);
pfLSourceVal(shad0, PFLS_INTENSITY, .5f);
shad1 = pfNewLSource();
pfLSourceMode(shad1, PFLS_SHADOW_ENABLE, 1);
pfLSourceAttr(shad1, PFLS_PROJ_FRUST, shadFrust);
pfLSourceColor(shad1, PFLT_DIFFUSE, 0.0f, 0.0f, 1.0f);
pfLSourceVal(shad1, PFLS_INTENSITY, .5f);
// Set DCSes to move lights around
shadDCS0 = pfNewDCS();
pfAddChild(shadDCS0, shad0);
pfAddChild(scene, shadDCS0);
shadDCS1 = pfNewDCS();
pfAddChild(shadDCS1, shad1);
pfAddChild(scene, shadDCS1);
NOTES
Shadows and Projected Texture functionality is not currently supported
under Linux.
To respect the limited number of active light sources allowed by graphics
library implementations, OpenGL Performer supports at most PF_MAX_LIGHTS
active light sources.
If you want light sources to affect only portions of the scene, then set
one or more pfLights on the pfGeoStates which are attached to the
pfGeoSets that you wish to illuminate (see pfGStateAttr and
PFSTATE_LIGHTS for further details).
Shadows are supported by InfinityReality only when using OpenGL.
PROJTEX and SHADOW lighting require local lighting for proper effects (-
pfLModelLocal).
SHADOW lighting on RealityEngine requires the depth buffer to be
configured with 32 bits (zbsize()). Note that it is legal to have
multisample buffers allocated in addition, the only requirement is that
Page 10
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
the non-multisampled depth buffer be 32 bits. Also note that on
RealityEngine, a 32-bit depth buffer requires 12-bit color. An alpha
plane is also required for multiple PROJTEX/SHADOW light sources.
SHADOW lighting on InfiniteReality works fine will all frame buffer
configurations, including multisample.
Shadows and projected textures are not clipped or properly computed
behind the pfLightSource. Instead, geometry behind the pfLightSource will
be textured randomly. The only workaround is to ensure that all geometry
behind the pfLightSource is not visible to the pfChannel.
Local lighting results in improper shading of flat-shaded triangle and
line strips (PFGS_FLAT_TRISTRIPS, PFGS_LINE_TRISTRIPS) which often
manifests itself as "faceting" of planar polygons. The only solution is
either to use infinite lighting or not use FLAT primitives. Note that
when using the OpenGL Performer triangle meshing routine, pfdMeshGSet,
the construction of non-FLAT strips is easily enforced with
pfdMesherMode(PFDMESH_LOCAL_LIGHTING, 1).
Multipass techniques are not compatible with stencil layer mode, the mode
is forced to PFGL_DECAL_DISPLACE.
SEE ALSO
pfChanTravFunc, pfChanTravMode, pfNode, pfSCS, pfDCS, pfGeoSet,
pfGeoState, pfLight, pfDelete
Page 11