pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
NAMEpfLightSource - Create pfLightSource, specify pfLightSource properties.
FUNCTION SPECIFICATION
#include <Performer/pf/pfLightSource.h>
pfLightSource::pfLightSource();
static pfType * pfLightSource::getClassType(void);
void pfLightSource::setAmbient(float r, float g, float b);
void pfLightSource::getAmbient(float* r, float* g,
float* b);
void pfLightSource::setColor(int which, float r, float g,
float b);
void pfLightSource::getColor(int which, float* r, float* g,
float* b);
void pfLightSource::setAtten(float constant, float linear,
float quadratic);
void pfLightSource::getAtten(float *constant, float *linear,
float *quadratic);
void pfLightSource::setSpotDir(float x, float y, float z);
void pfLightSource::getSpotDir(float* x, float* y,
float* z);
void pfLightSource::setSpotCone(float f1, float f2);
void pfLightSource::getSpotCone(float* f1, float* f2);
void pfLightSource::setPos(float x, float y, float z,
float w);
void pfLightSource::getPos(float* x, float* y, float* z,
float* w);
void pfLightSource::on(void);
void pfLightSource::off(void);
int pfLightSource::isOn(void);
void pfLightSource::setMode(int mode, int val);
Page 1
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
int pfLightSource::getMode(int mode);
void pfLightSource::setVal(int mode, float val);
float pfLightSource::getVal(int mode);
void pfLightSource::setAttr(int attr, void *obj);
void* pfLightSource::getAttr(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. This is also true
for ancestor classes of class pfNode.
pfGroup * pfNode::getParent(int i);
int pfNode::getNumParents(void);
void pfNode::setBound(pfSphere *bsph, int mode);
int pfNode::getBound(pfSphere *bsph);
pfNode* pfNode::clone(int mode);
pfNode* pfNode::bufferClone(int mode, pfBuffer *buf);
int pfNode::flatten(int mode);
int pfNode::setName(const char *name);
const char * pfNode::getName(void);
pfNode* pfNode::find(const char *pathName, pfType *type);
pfNode* pfNode::lookup(const char *name, pfType* type);
int pfNode::isect(pfSegSet *segSet, pfHit **hits[]);
void pfNode::setTravMask(int which, uint mask, int setMode,
int bitOp);
uint pfNode::getTravMask(int which);
void pfNode::setTravFuncs(int which, pfNodeTravFuncType pre,
pfNodeTravFuncType post);
void pfNode::getTravFuncs(int which, pfNodeTravFuncType *pre,
pfNodeTravFuncType *post);
void pfNode::setTravData(int which, void *data);
void * pfNode::getTravData(int which);
void pfNode::setTravMode(int which, int mode, int val);
int pfNode::getTravMode(int which, int mode) const;
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* pfObject::operator new(size_t);
void* pfObject::operator new(size_t, pfFluxMemory *fmem);
void pfObject::setUserData(void *data);
void pfObject::setUserData(int slot, void *data);
void* pfObject::getUserData(pfObject *obj);
Page 2
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
void* pfObject::getUserData(pfObject *obj, int slot);
int pfObject::getNumUserData();
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.
void* pfMemory::getData(const void *ptr);
pfType * pfMemory::getType();
int pfMemory::isOfType(pfType *type);
int pfMemory::isExactType(pfType *type);
const char * pfMemory::getTypeName();
int pfMemory::copy(pfMemory *src);
int pfMemory::compare(const pfMemory *mem);
void pfMemory::print(uint which, uint verbose, char *prefix,
FILE *file);
int pfMemory::getArena(void *ptr);
void* pfMemory::getArena();
int pfMemory::ref();
int pfMemory::unref();
int pfMemory::unrefDelete();
int pfMemory::unrefGetRef();
int pfMemory::getRef();
int pfMemory::checkDelete();
int pfMemory::isFluxed();
void * pfMemory::getArena();
int pfMemory::getSize();
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.
new pfLightSource creates and returns a handle to a pfLightSource. Like
other pfNodes, pfLightSources are always allocated from shared memory and
cannot be created statically, on the stack or in arrays. pfLightSources
should be deleted using pfDelete rather than the delete operator.
pfLightSource::getClassType returns the pfType* for the class
pfLightSource. The pfType* returned by pfLightSource::getClassType is
the same as the pfType* returned by invoking the virtual function getType
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 the member function isOfType
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 (but not
inherited): setAmbient, getAmbient, setColor, getColor, setAtten,
getAtten, setPos, getPos, setSpotCone, getSpotCone, setSpotDir,
Page 3
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
getSpotDir, on, off, isOn. The reader is referred to the pfLight man
page for details on the routine description.
When enabled by pfLightSource::on, 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 pfLightSource::off.
pfLightSources are processed somewhat differently than other nodes. If
the PFCULL_IGNORE_LSOURCES mode is not enabled by pfChannel::setTravMode,
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 (-
pfNode::setTravFuncs) will be invoked multiple times.
pfLightSources are culled to the viewing frustum only if they have been
assigned a non-null bounding volume (pfNode::setBound). 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
pfChannel::setTravFunc). 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 pfNode::setTravFuncs 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 = new pfLightSource;
/* Set slightly yellow color */
sun->setColor(PFLT_DIFFUSE, 1.0f, 1.0f, .8f);
/* Set a high ambient level */
sun->setColor(PFLT_AMBIENT, .4f, .4f, .3f);
Page 4
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
/* Time of day is high noon */
sun->setPos(0.0f, 1.0f, 0.0f, 0.0f);
scene->addChild(sun);
A pfLightSource supports 3 different lighting mechanisms as listed in the
following table:
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.
Page 5
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
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
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
pfLightSource::setMode. 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.
pfChannel::setTravMode 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
pfEarthSky::setColor. 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 pfLightSource::setAttr. obj should be an
intensity-alpha (2-component) pfTexture* with identical intensity and
Page 6
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
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
pfLightSource::setVal. 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 pfLightSource::setAttr. 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
lsource.setMode(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 pfLightSource::setVal 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 pfLightSource::setMode and by
specifying a pfFog with the PFLS_PROJ_FOG token to
pfLightSource::setAttr. The pfFog color should be the ambient color of
the projected texture. Only a single range-attenuated projected
Page 7
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pfLightSource is supported for a given pfChannel.
With IrisGL A pfLightSource's intensity is set with the PFLS_INTENSITY
token to pfLightSource::setVal. 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
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 = new pfTexture;
spotTex->loadFile("spot.inta");
// Create and configure projected texture frustum
spotFrust = new pfFrustum;
spotFrust->makeSimple(60.0f);
spotFrust->setNearFar(1.0f, 100.0f);
// Create and configure range-attenuation fog model
spotFog = new pfFog;
spotFog->setColor(0.1f, 0.1f, 0.1f);
spotFog->setRange(0.0f, 100.0f);
// Create and configure projected texture light source
spot = new pfLightSource;
spot->setAttr(PFLS_PROJ_TEX, spotTex);
spot->setAttr(PFLS_PROJ_FRUST, spotFrust);
spot->setAttr(PFLS_PROJ_FOG, spotFog);
spot->setMode(PFLS_PROJTEX_ENABLE, 1);
// Set spotDCS to viewing matrix to move light around with eye
spotDCS = new pfDCS;
spotDCS->addChild(spot);
scene->addChild(spotDCS);
// Enable emissive pass since scene has emissive surfaces
Page 8
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
chan->setTravMode(PFTRAV_MULTIPASS, PFMPASS_EMISSIVE_PASS);
Example 3: Multiple, shadow-casting, colored pfLightSources
pfLightSource *shad0, *shad1;
pfDCS *shadDCS0, *shadDCS1;
pfFrustum *shadFrust;
pfChannel *chan;
pfEarthSky *esky;
// Create and configure shadow frustum
shadFrust = new pfFrustum;
shadFrust->makeSimple(60.0f);
shadFrust->setNearFar(1.0f, 100.0f);
// Create and configure shadow casting light sources
shad0 = new pfLightSource;
shad0->setMode(PFLS_SHADOW_ENABLE, 1);
shad0->setAttr(PFLS_PROJ_FRUST, shadFrust);
shad0->setColor(PFLT_DIFFUSE, 1.0f, 0.0f, 0.0f);
shad0->setVal(PFLS_INTENSITY, .5f);
shad1 = new pfLightSource;
shad1->setMode(PFLS_SHADOW_ENABLE, 1);
shad1->setAttr(PFLS_PROJ_FRUST, shadFrust);
shad1->setColor(PFLT_DIFFUSE, 0.0f, 0.0f, 1.0f);
shad1->setVal(PFLS_INTENSITY, .5f);
// Set DCSes to move lights around
shadDCS0 = new pfDCS;
shadDCS0->addChild(shad0);
scene->addChild(shadDCS0);
shadDCS1 = new pfDCS;
shadDCS1->addChild(shad1);
scene->addChild(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.
Page 9
pfLightSource(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
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 pfGeoState::setAttr 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 (-
pfLightModel::setLocal).
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
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
pfChannel, pfNode, pfSCS, pfDCS, pfGeoSet, pfGeoState, pfLight, pfDelete
Page 10