pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
NAME
pfChannel, pfApp, pfCull, pfDraw, pfLPoint, pfDrawBin, pfDrawScene,
pfNodePickSetup - Set and get pfChannel definition parameters.
FUNCTION SPECIFICATION
#include <Performer/pf/pfChannel.h>
pfChannel::pfChannel(pfPipe *pipe);
static pfType * pfChannel::getClassType(void);
pfPipe * pfChannel::getPipe(void);
void pfChannel::setViewport(float l, float r, float b,
float t);
void pfChannel::getViewport(float* l, float* r, float* b,
float* t);
void pfChannel::getOrigin(int *xo, int *yo);
void pfChannel::getSize(int *xs, int *ys);
void pfChannel::setLODState(const pfLODState *ls);
void pfChannel::getLODState(pfLODState *ls);
void pfChannel::setLODStateList(pfList *lsList);
pfList * pfChannel::getLODStateList(void);
int pfChannel::getPWinIndex(void);
pfPipeWindow * pfChannel::getPWin(void);
void pfChannel::setTravFunc(int trav, pfChanFuncType func);
pfChanFuncType pfChannel::getTravFunc(int trav);
void * pfChannel::allocChanData(int size);
void pfChannel::setChanData(void *data, size_t size);
void * pfChannel::getChanData(void);
size_t pfChannel::getChanDataSize(void);
void pfChannel::passChanData(void);
void pfChannel::clear(void);
Page 1
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
int pfChannel::attach(pfChannel* chan1);
int pfChannel::detach(pfChannel* chan1);
int pfChannel::ASDattach(pfChannel* chan1);
int pfChannel::ASDdetach(pfChannel* chan1);
void pfChannel::setShare(uint mask);
uint pfChannel::getShare(void);
void pfChannel::setFOV(float horiz, float vert);
void pfChannel::getFOV(float* horiz, float* vert);
void pfChannel::setNearFar(float near, float far);
void pfChannel::getNearFar(float* near, float* far);
void pfChannel::setAutoAspect(int which);
int pfChannel::getAutoAspect(void);
void pfChannel::getBaseFrust(pfFrustum *frust);
void pfChannel::getPtope(pfPolytope *ptope);
void pfChannel::makePersp(float left, float right,
float bottom, float top);
void pfChannel::makeInfPersp(float left, float right,
float bottom, float top);
void pfChannel::makeOrtho(float left, float right,
float bottom, float top);
void pfChannel::makeSimple(float fov);
int pfChannel::getFrustType(void);
void pfChannel::setAspect(int which,
float widthHeightRatio);
float pfChannel::getAspect(void);
void pfChannel::orthoXform(pfChannel* src,
const pfMatrix &mat);
void pfChannel::getNear(pfVec3 &ll, pfVec3 &lr, pfVec3 &ul,
pfVec3 &ur);
Page 2
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
void pfChannel::getFar(pfVec3 &ll, pfVec3 &lr, pfVec3 &ul,
pfVec3 &ur);
int pfChannel::getEye(pfVec3 &eye);
void pfChannel::apply(void);
int pfChannel::contains(const pfVec3 &pt, pfChannel* chan);
int pfChannel::contains(const pfSphere* sph);
int pfChannel::contains(const pfCylinder* cyl);
int pfChannel::contains(const pfBox* box);
void pfChannel::setCullPtope(const pfPolytope *ptope);
void pfChannel::getCullPtope(pfPolytope *ptope, int space);
int pfChannel::pick(int mode, float px, float py,
float radius, pfHit **picklist[]);
int pfChannel::isect(pfNode *node, pfSegSet *segSet,
pfHit **hits[], pfMatrix *mat);
void pfChannel::setScene(pfScene *scene);
pfScene * pfChannel::getScene(void);
void pfChannel::setESky(pfEarthSky *sky);
pfEarthSky * pfChannel::getESky(void);
void pfChannel::setGState(pfGeoState *gstate);
pfGeoState * pfChannel::getGState(void);
void pfChannel::setGStateTable(pfList *gstable);
pfList* pfChannel::getGStateTable(void);
void pfChannel::setStressFilter(float frac, float low,
float high, float scale, float max);
void pfChannel::getStressFilter(float *frac, float *low,
float *high, float *scale, float *max);
void pfChannel::setStress(float stress);
float pfChannel::getStress(void);
Page 3
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
float pfChannel::getLoad(void);
void pfChannel::setTravMode(int trav, int mode);
int pfChannel::getTravMode(int trav);
void pfChannel::setTravMask(int trav, uint mask);
uint pfChannel::getTravMask(int trav);
void pfChannel::setBinSort(int bin, int sortType,
uint64_t *sortOrders);
int pfChannel::getBinSort(int bin, uint64_t *sortOrders);
void pfChannel::setBinOrder(int bin, int order);
int pfChannel::getBinOrder(int bin);
int pfChannel::getFreeBin(void);
void pfChannel::setBinSortPriority(int bin, int priority);
int pfChannel::getBinSortPriority(int bin);
void pfChannel::setBinChildOrderMask(int bin,
uint64_t orderMask);
uint64_t pfChannel::getBinChildOrderMask(int bin);
void pfChannel::setBinFlags(int bin, int flags);
int pfChannel::getBinFlags(int bin);
void pfChannel::setBinCallBack(int bin, int type,
pfDListFuncType func);
pfDListFuncType pfChannel::getBinCallBack(int bin, int type);
void pfChannel::setBinUserData(int bin, void *userData,
int size);
void * pfChannel::getBinUserData(int bin, int *size);
int pfChannel::findSubBin(int bin1, int bin2, int create);
int pfChannel::findBinParent(int bin, int lastKnownParent);
pfCullProgram * pfChannel::getCullProgram(void);
Page 4
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
void pfChannel::setView(pfVec3 &xyz, pfVec3 &hpr);
void pfChannel::getView(pfVec3 &xyz, pfVec3 &hpr);
void pfChannel::setViewMat(pfMatrix &mat);
void pfChannel::getViewMat(pfMatrix &mat);
void pfChannel::setViewOffsets(pfVec3 &xyz, pfVec3 &hpr);
void pfChannel::getViewOffsets(pfVec3 &xyz, pfVec3 &hpr);
void pfChannel::getOffsetViewMat(pfMatrix &mat);
pfFrameStats * pfChannel::getFStats(void);
int pfChannel::setStatsMode(uint mode, uint val);
void pfChannel::drawStats(void);
void pfChannel::setLODAttr(int attr, float val);
float pfChannel::getLODAttr(int attr);
void pfChannel::setProjMode(int mode);
int pfChannel::getProjMode(void);
pfPipeVideoChannel *
pfChannel::getPVChan(void);
void pfChannel::setPWinPVChanIndex(int num);
int pfChannel::getPWinPVChanIndex(void);
void pfChannel::setOutputViewport(float l, float r, float b,
float t);
void pfChannel::getOutputViewport(float *l, float *r,
float *b, float *t);
void pfChannel::getOutputOrigin(int *xo, int *yo);
void pfChannel::getOutputSize(int *xs, int *ys);
void pfChannel::setPixScale(float s);
float pfChannel::getPixScale(void);
void pfChannel::setMinPixScale(float min);
Page 5
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
float pfChannel::getMinPixScale(void);
void pfChannel::setMaxPixScale(float max);
float pfChannel::getMaxPixScale(void);
int pfChannel::getUserFrustType(void);
void pfChannel::getBaseUserFrust(pfFrustum *frust);
float pfChannel::getUserAspect(void);
void pfChannel::getUserFOV(float *fovH, float *fovV);
void pfChannel::getUserNearFar(float *n, float *f);
void pfChannel::getUserNear(pfVec3 &ll, pfVec3 &lr,
pfVec3 &ul, pfVec3 &ur);
void pfChannel::getUserFar(pfVec3 &ll, pfVec3 &lr,
pfVec3 &ul, pfVec3 &ur);
void pfChannel::getUserPtope(pfPolytope *dst);
int pfChannel::getUserEye(pfVec3& eye);
void pfChannel::getUserLeftRightBottomTop(float *l,
float *r, float *b, float *t);
int pfChannel::userContains(const pfVec3& pt);
int pfChannel::userContains(const pfSphere *sphere);
int pfChannel::userContains(const pfBox *box);
int pfChannel::userContains(const pfCylinder *cyl);
void pfChannel::setCallig(pfCalligraphic* callig);
pfCalligraphic* pfChannel::getCallig(void);
pfCalligraphic* pfChannel::getCurCallig(void);
void pfChannel::setCalligEnable(int enable)
int pfChannel::getCalligEnable(void);
void pfApp(void);
void pfCull(void);
Page 6
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
void pfDraw(void);
void pfLPoint(void);
void pfDrawBin(int bin);
void pfDrawScene(void);
void pfNodePickSetup(pfNode *node);
PARENT CLASS FUNCTIONS
The OpenGL Performer class pfChannel is derived from the parent class
pfObject, so each of these member functions of class pfObject are also
directly usable with objects of class pfChannel. This is also true for
ancestor classes 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);
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 pfChannel 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();
Page 7
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
PARAMETERS
chan identifies a pfChannel.
node identifies a pfNode.
trav is a symbolic token identifying a traversal:
PFTRAV_CULL
PFTRAV_DRAW
DESCRIPTION
A pfChannel is essentially a view onto a scene. new pfChannel creates a
new pfChannel on the pfPipe identified by pipe. The new pfChannel will
be rendered by the pipe into a pfPipeWindow window associated with pipe
(See pfPipeWindow::config). new pfChannel creates and returns a handle
to a pfChannel. pfChannels are always allocated from shared memory and
cannot be created statically, on the stack or in arrays.
pfChannel::getClassType returns the pfType* for the class pfChannel. The
pfType* returned by pfChannel::getClassType is the same as the pfType*
returned by invoking the virtual function getType on any instance of
class pfChannel. 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.
PIPE WINDOWS, PIPES, AND CHANNELS
pfChannel::getPipe returns the parent pfPipe of the pfChannel.
pfChannel::getPWin returns the pfPipeWindow of the pfChannel.
Multiple pfChannels may be rendered by a single pfPipe into a single
pfPipeWindow. It is recommended that multiple pfChannels rather than
multiple pfPipes be used to render multiple views on a single hardware
pipeline. If necessary, multiple pfPipeWindows can be rendered by a
single pfPipe on a single hardware pipeline. The handle returned by new
pfChannel should be used to identify the pfChannel in OpenGL Performer
routines.
Upon creation, pfChannels are automatically assigned to the first
pfPipeWindow of its parent pfPipe. pfChannel::getPWin will return the
pfPipeWindow of the pfChannel.
Channels of a pfPipeWindow are drawn in the order in which they are
assigned to the pfPipeWindow. pfChannel::getPWinIndex can be used to get
the position of a channel in its pfPipeWindow list. A return value of
(-1) indicates that the channel is not assigned to a pfPipeWindow.
Channels can be re-ordered in their pfPipeWindow, or moved to other
pfPipeWindows via list style API on pfPipeWindows. See the pfPipeWindow
man page for more information.
Page 8
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
All active pfChannels are culled and drawn by pfFrame. A pfChannel is by
default active but can be selectively turned on and off by PFDRAW_ON and
PFDRAW_OFF arguments to pfChannel::setTravMode. Multiple pfChannels on a
pfPipe will be drawn only if they are assigned to a pfPipeWindow and will
be drawn in the order they were assigned to that pfPipeWindow.
pfChannel::setViewport specifies the fractional viewport used by the
pfChannel. l, r, b, t specify the left, right, bottom, and top extents
of a viewport in the range 0.0 to 1.0. The fractional viewport is
relative to the parent pfPipe's graphics window. Channel viewports on a
single pfPipe may overlap. Viewport extents are clamped to the range 0.0
to 1.0.
pfChannel::getViewport copies the fractional viewport of the pfChannel
into l, r, b, t.
pfChannel::setOutputViewport sets the area of the pfChannel viewport that
is to be output to display. Typically this does not need to be set and
is by default equal to that set by pfChannel::setViewportLn. However, a
separate output viewport is interesting for some advanced multichannel
rendering operations and is used internally by OpenGL Performer for
dynamic video resizing (DVR).
pfChannel::setProjMode is used to set the projection mode, which is
important when using the Dynamic Video Resizing (DVR) feature of
InfiniteReality graphics systems. In operation, the two modes are nearly
indistinguishable and are mostly important in the case where a pfChannel
has a draw callback function that expects the viewport to be set to the
default (PFCHAN_PROJ_OUTPUT_VIEWPORT) value. The mode argument is one of
these values:
PFCHAN_PROJ_OUTPUT_VIEWPORT
This is the default mode of operation. it sets the graphics
library viewport and scissor mask (see glScissor(3g)) to the
output viewport of the pfChannel, which typically is also the
full viewport.
PFCHAN_PROJ_VIEWPORT
The viewport will be set to the full pfChannel viewport but the
screen scissor mask will be set to the pfChannel output
viewport.
PFCHAN_PROJ_WINDOW
This mode sets the graphics library viewport for the pfChannel
to be the full extent of the pfPipeWindow, then uses the
projection matrix and GL scissor mask to scale down the
displayed area to the output viewport. This can be important
when using the DVR facility since it reduces any jitter that
might otherwise occur between adjacent channels caused by
clamping viewport boundaries to integer pixel values.
Page 9
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
Use pfChannel::getProjMode to get the current setting of a channel's
projection mode.
pfChannel::getOrigin copies the window coordinates of the origin of
chan's viewport into xo and yo.
pfChannel::getSize copies the X and Y pixel sizes of the pfChannel's
viewport into xs and ys.
APPLICATION-DEFINED CALLBACKS AND DATA
Although OpenGL Performer normally handles all culling and drawing,
invocation of user written and registered extension functions (callback
functions) is supported to allow custom culling and drawing by the
application. Furthermore, OpenGL Performer manages callback data such
that when configured for multiprocessing, data contention and
synchronization issues are handled transparently.
pfChannel::setTravFunc sets the application, cull, draw or light points
process callback functions for the pfChannel. The trav argument
specifies which traversal is to be set and is one of: PFTRAV_APP,
PFTRAV_CULL, PFTRAV_DRAW or PFTRAV_LPOINT. User-data that is passed to
these functions is allocated on a per-channel basis by
pfChannel::allocChanData. pfChannel::allocChanData returns a pointer to
a word-aligned buffer of shared memory of size bytes. Alternately,
applications can provide passthrough data with pfChannel::setChanData.
data is a memory block of size bytes which should be allocated from a
shared malloc arena visible to all OpenGL Performer processes when
multiprocessing (see pfMultiprocess).
pfChannel::getChanDataSize returns the size of the pfChannel's
passthrough data block. pfChannel::getChanData returns a pointer to a
buffer that was set by pfChannel::setChanData or allocated by
pfChannel::allocChanData or NULL if no buffer has been allocated or set.
pfChannel::getTravFunc returns the app, cull or draw callback functions
for chan or NULL if the callback has not been set.
In order to propagate user data downstream to the cull and draw
callbacks, pfChannel::passChanData should be called whenever the user
data is changed to indicate that the data should be "passed through" the
OpenGL Performer rendering pipeline. The next call to pfFrame will copy
the channel buffer into internal OpenGL Performer memory so that the
application will then be free to modify data in the buffer without fear
of corruption.
In the cull phase of the rendering pipeline, OpenGL Performer invokes the
cull callback with a pointer to the pfChannel being culled and a pointer
to the pfChannel's data buffer. The cull callback may modify data in the
buffer. The potentially modified buffer is then copied and passed to the
user's draw callback. Modifications to the data buffer are not visible
upstream. For example, changes made by the cull or draw process are not
Page 10
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
seen by the application process.
When OpenGL Performer is configured for multiprocessing (see
pfMultiprocess), it is important to realize that the cull and draw
callbacks may be invoked from different processes and thus may run in
parallel with each other as well as with the main application process.
OpenGL Performer provides both shared arenas (see pfGetSemaArena and
pfGetSharedArena) and channel data (pfChannel::allocChanData) for
interprocess communication.
With user callbacks, it is possible to extend or even completely replace
OpenGL Performer actions with custom traversal, culling and drawing.
pfApp, pfCull, pfDraw and pfLPoint trigger the default OpenGL Performer
processing. This default processing is invoked automatically in the
absence of any user callbacks specified by pfChannel::setTravFunc,
otherwise the user callback usually invokes them directly.
pfApp carries out the application traversal for the channel and should
only be invoked in the application callback specified by
pfChannel::setTravFunc. The application callback is invoked once for
each channel group that is sharing PFCHAN_APPFUNC.
pfLPoint runs in parallel with draw. It opens a ring display list and
preprocess the light points in the bin that has been provided by the
culling. The display list stays opened after the call to pfLPoint() so
every command issued after that call will be sent over to the draw
process. Note that every command issued before pfLPoint() will be
immediately executed, such as pfCalligraphic parametrisation for the
current frame. Note also that the light point process does not have any
graphic context and therefore it is forbidden to do some direct graphic
calls here.
pfCull should only be called in the cull callback and causes OpenGL
Performer to cull the current channel and generate an OpenGL Performer
display list (see pfDispList) suitable for rendering if the
PFMP_CULL_DL_DRAW multiprocessing mode is enabled (see pfMultiprocess).
Then, in the draw callback only, pfDraw will traverse the pfDispList and
send rendering commands to the graphics hardware, thus drawing the scene.
If the PFMP_CULL_DL_DRAW multiprocessing mode is not set then all
display-listable operations will be applied directly to the graphics
pipeline rather than accumulated in a pfDispList for subsequent drawing.
In essence, the draw process does the work of both pfCull and pfDraw
without the intermediate step of building a pfDispList. This mode avoids
the overhead of building and traversing a pfDispList but consequently is
not suitable for multipass renderings which require multiple invocations
of pfDraw.
When the draw callback is invoked, the graphics context will already have
been properly configured for drawing the pfChannel. Specifically, the
viewport, perspective and viewing matrices are set to the correct values.
In addition, graphics library light sources corresponding to the active
Page 11
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pfLightSources in the scene will be enabled so that geometry rendered in
the draw callback will be properly lit. User modifications of this
initial state are not reset by pfDraw.
If a draw callback is specified, OpenGL Performer will not automatically
clear the viewport, leaving control of this to the application.
pfChannel::clear called from the draw callback will clear the channel
viewport. If the pfChannel has a pfEarthSky (see pfChannel::setESky),
then the pfEarthSky will be drawn. Otherwise, the viewport will be
cleared to black and the z-buffer cleared to its maximum value.
By default, pfFrame causes pfCull and pfDraw to be invoked for each
active pfChannel. It is legal for the draw callback to call pfDraw more
than once for multipass renderings. Note that pfDraw will render the
internal multipass pfLightSource projected texture lights and shadows
every time it is called. pfDrawScene may be more convenient as it will
draw the scene without the internal multipass.
Example 1: Set up channel callbacks and passthrough data
typedef struct
{
int val;
} PassData;
void cullFunc(pfChannel *chan, void *data);
void drawFunc(pfChannel *chan, void *data);
int
main()
{
PassData *pd;
/* Initialize OpenGL Performer */
pfInit();
pfConfig();
/* Create and initialize pfChannel 'chan' */
chan = new pfChannel(pfGetPipe(0));
:
/* Setup channel passthrough data */
pd = (PassData*)chan->allocChanData(sizeof(PassData));
/* Bind cull and draw callback functions to channel */
chan->setTravFunc(PFTRAV_CULL, cullFunc);
chan->setTravFunc(PFTRAV_DRAW, drawFunc);
pd->val = 0;
chan->passChanData();
pfFrame();
Page 12
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
:
}
void
cullFunc(pfChannel *chan, void *data)
{
PassData *pd = (PassData*)data;
pd->val++;
pfCull();
}
void
drawFunc(pfChannel *chan, void *data)
{
PassData *pd = (PassData*)data;
fprintf(stderr, "%ld\n", pd->val);
chan->clear();
pfDraw();
}
SHARING ATTRIBUTES THROUGH CHANNEL GROUPS
OpenGL Performer supports the notion of a 'channel group' which is a
collection of pfChannels that share certain attributes. A channel group
is created by attaching a pfChannel to another with pfChannel::attach.
If the pfChannel or chan1 are themselves members of a channel group, then
all channels that are grouped with either the pfChannel or chan1 are
combined into a single channel group. All attached channels acquire the
share mask and shared attributes of the channel group. A channel is
removed from a channel group by pfChannel::detach.
The attributes shared by the members of a channel group are specified by
the mask argument to pfChannel::setShare. By definition, all channels in
a group have the same share mask. A pfChannel that is attached to a
channel group inherits the share mask of the group. mask is a bitwise OR
of the following tokens which enumerate the attributes that can be
shared:
PFCHAN_FOV
Horizontal and vertical fields of view are shared.
PFCHAN_VIEW
The view position and orientation are shared.
PFCHAN_VIEW_OFFSETS
The XYZ and HPR offsets from the view direction are shared.
PFCHAN_NEARFAR
The near and far clip planes are shared.
Page 13
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
PFCHAN_SCENE
All channels display the same scene.
PFCHAN_EARTHSKY
All channels display the same earth-sky model.
PFCHAN_STRESS
All channels use the same stress filter parameters.
PFCHAN_LOD
All channels use the same LOD modifiers.
PFCHAN_SWAPBUFFERS
All channels swap buffers at the same time, even when the
channels are on multiple pfPipes.
PFCHAN_SWAPBUFFERS_HW
All channels swap buffers at the same time. Under IrisGL the
GANGDRAW feature of the mswapbuffers function, under OpenGL the
glxSwapBarrier extension, is used to synchronize buffer
swapping through hardware interlocking. When channels are
distributed across more than one pipe, the SwapReady signal is
to be connected between the pipes. This signal can also be
used to synchronize graphics pipelines across multiple
machines.
PFCHAN_STATS_DRAWMODE
All channels draw the same statistics graph.
PFCHAN_APPFUNC
The application callback is invoked once for all channels
sharing PFCHAN_APPFUNC.
PFCHAN_CULLFUNC
All channels invoke the same channel cull callback.
PFCHAN_DRAWFUNC
All channels invoke the same channel draw callback.
PFCHAN_LPOINTFUNC
All channels invoke the same channel light points callback.
PFCHAN_VIEWPORT
All channels use the same viewport specification.
pfChannel::getShare returns the share mask of the pfChannel. The default
attributes cause channels within a share group to share all attributes
except PFCHAN_VIEW_OFFSETS, PFCHAN_VIEWPORT and PFCHAN_SWAPBUFFERS_HW.
Channel groups are useful for multichannel simulations where many of the
viewing parameters are the same across pfChannels. For example, a 3-
channel simulation consisting of left, middle, and right views typically
Page 14
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
shares the near and far clipping planes. With a channel group, the
clipping planes need only be set on a single pfChannel, say the middle
one, and all other pfChannels in the group will acquire the same
settings.
Example 1: Set up a single pipe, 3-channel simulation
left = new pfChannel(pfGetPipe(0));
middle = new pfChannel(pfGetPipe(0));
right = new pfChannel(pfGetPipe(0));
/* Form channel group with middle as the "master" */
middle->attach(left);
middle->attach(right);
/* Set FOV of all channels */
middle->makeSimple(45.0f);
middle->setAutoAspect(PFFRUST_CALC_VERT);
/* Set clipping planes of all channels */
middle->setNearFar(1.0f, 2000.0f);
hprOffsets->set(0.0f, 0.0f, 0.0f);
xyzOffsets->set(0.0f, 0.0f, 0.0f);
/*
* Set up viewport and viewing offsets.
* Note that these are not shared by default.
*/
left->setViewport(0.0f, 1.0f/3.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = 45.0f;
left->setViewOffsets(xyzOffsets, hprOffsets);
middle->setViewport(1.0f/3.0f, 2.0f/3.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = 0.0f;
middle->setViewOffsets(xyzOffsets, hprOffsets);
right->setViewport(2.0f/3.0f, 1.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = -45.0f;
right->setViewOffsets(xyzOffsets, hprOffsets);
VIEWING FRUSTUM
Many pfChannel frustum routines are borrowed from pfFrustum (but not
inherited). These routines have the identical prototype as the pfFrustum
routines but operate on the pfChannel's internal viewing frustum:
makeSimple, makePersp, makeInfPersp, makeOrtho, setNearFar, getNearFar,
getFOV, setAspect, getAspect, getFrustType, orthoXform, getNear, getFar,
getEye, apply, and contains. The reader is referred to the pfFrustum man
page for details on the function descriptions.
Page 15
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
In addition to the pfFrustum routines, OpenGL Performer provides the
pfChannel::setFOV and pfChannel::setAutoAspect convenience routines.
The horiz and vert arguments to pfChannel::setFOV specify total
horizontal and vertical fields of view (FOV) in degrees. If either angle
is <= 0.0 or >= 180.0, OpenGL Performer will automatically compute that
field of view based on the other specified field of view and the aspect
ratio of the pfChannel viewport. If both angles are defaulted in this
way, OpenGL Performer will use its default of horiz=45.0 with vert
matched to the aspect ratio of the pfChannel. Note that the aspect ratio
of a pfChannel is defined by its fractional viewport as well as the pixel
size of its physical display window.
pfChannel::setFOV constructs a on-axis frustum, one where the line from
the eyepoint passing through the center of the image is perpendicular to
the projection plane. pfChannel::makeSimple also creates an on-axis
frustum but both horizontal and vertical fields of view are specified
with fov.
pfChannel::getFOV copies the total horizontal and vertical fields of view
into horiz and vert respectively. If an angle is matched to the aspect
ratio of the pfChannel, then the computed angle is returned.
The which argument to pfChannel::setAutoAspect specifies which FOV extent
to automatically match to the aspect ratio of the pfChannel's viewport.
which is a symbolic token and is one of:
PFFRUST_CALC_NONE
Do not automatically modify field of view.
PFFRUST_CALC_HORIZ
Automatically modify horizontal FOV to match channel aspect.
PFFRUST_CALC_VERT
Automatically modify vertical FOV to match channel aspect.
Automatic aspect ratio matching is useful for situations where the
initial size of the display window is not known or where the display
window may change size during runtime. Aspect ratio matching guarantees
that the image will not be distorted in either horizontal or vertical
dimensions. pfChannel::makePersp and pfChannel::makeOrtho disable
automatic aspect ratio matching since it is assumed that the viewing
frustum aspect ratio is completely specified by these commands.
pfChannel::setNearFar specifies the near and far clip distances of the
viewing frustum. near and far are the positive, world-coordinate
distances along the viewing ray from the eye point to the near and far
clipping planes which are parallel to the viewing plane.
pfChannel::getNearFar copies the near and far clipping distances into
near and far. The default values are 1.0 for the near plane and 1000.0
for the far plane.
Page 16
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pfChannel::getBaseFrust copies the base viewing frustum of the pfChannel
into frust. The base viewing frustum has its eyepoint at the origin and
its viewing direction as the +Y axis. The base frustum of a pfChannel is
transformed into world coordinates by the viewing transformation (see
pfChannel::setView). pfChannel::orthoXform transforms the base frustum
of src by mat and copies the result into the base frustum of the dst
pfChannel. pfChannel::getPtope copies the transformed base frustum into
dst.
Example 1: Two equivalent ways of defining a typical viewing channel.
This method is the easiest and most common.
/* Set up a simple viewing frustum */
chan = new pfChannel(pipe0);
/*
* Set horizontal FOV to 45 degrees and automatically match
* vertical FOV to channel viewport.
*/
chan->setFOV(45.0f, -1.0f);
Here's how to do the same thing using the basic primitives.
/* Set up a simple viewing frustum */
chan = new pfChannel(pipe0);
/*
* Set horizontal FOV to 45 degrees and automatically match
* vertical FOV to channel viewport.
*/
chan->makeSimple(45.0f);
chan->setAutoAspect(PFFRUST_CALC_VERT);
Example 2: Set up a 4 channel, 4 pipe video wall with total horizontal
and vertical FOVs of 90 degrees.
/*
* ul == upper left ur == upper right
* ll == lower left lr == lower right
*/
llChan = new pfChannel(pfGetPipe(0));
lrChan = new pfChannel(pfGetPipe(1));
urChan = new pfChannel(pfGetPipe(2));
ulChan = new pfChannel(pfGetPipe(3));
/* Form channel group with urChan as the "master" */
urChan->attach(llChan);
Page 17
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
urChan->attach(lrChan);
urChan->attach(ulChan);
/*
* Share viewport but not field of view
* in addition to the default shared attributes.
*/
share = urChan->getShare();
urChan->setShare((share & ~PFCHAN_FOV) | PFCHAN_VIEWPORT );
/*
* Set up off-axis viewing frusta which "tile" video wall.
* pfChannel viewport aspect ratio must be 1:1 or image will
* be distorted.
*/
llChan->makePersp(-1.0f, 0.0f, -1.0f, 0.0f);
lrChan->makePersp( 0.0f, 1.0f, -1.0f, 0.0f);
urChan->makePersp( 0.0f, 1.0f, 0.0f, 1.0f);
ulChan->makePersp(-1.0f, 0.0f, 0.0f, 1.0f);
urChan->setNearFar(1.0f, 2000.0f);
Example 3: Set up a single pipe, 3-channel simulation.
left = new pfChannel(pfGetPipe(0));
middle = new pfChannel(pfGetPipe(0));
right = new pfChannel(pfGetPipe(0));
/* Form channel group with middle as the "master" */
middle->attach(left);
middle->attach(right);
/* Set FOV of all channels */
middle->makeSimple(45.0f);
middle->setAutoAspect(PFFRUST_CALC_VERT);
/* Set clipping planes of all channels */
middle->setNearFar(1.0f, 2000.0f);
hprOffsets[PF_P] = 0.0f;
hprOffsets[PF_R] = 0.0f;
xyzOffsets->set(0.0f, 0.0f, 0.0f);
/*
* Set up viewport and viewing offsets.
* Note that these are not shared by default.
*/
left->setViewport(0.0f, 1.0f/3.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = 45.0f;
left->setViewOffsets(hprOffsets, xyzOffsets);
Page 18
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
middle->setViewport(1.0f/3.0f, 2.0f/3.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = 0.0f;
middle->setViewOffsets(hprOffsets, xyzOffsets);
right->setViewport(2.0f/3.0f, 1.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = -45.0f;
right->setViewOffsets(hprOffsets, xyzOffsets);
Example 4: Custom culling to pfChannel viewing frustum.
/*
* User-supplied cull callback (see pfChannel::setTravFunc)
*/
extern void
myCullFunc(pfChannel *chan, void *data)
{
pfBox *boundingBox = (pfBox*)data;
if (chan->contains(boundingBox))
drawGSetsWithinBoundingBox();
}
pfChannel::ASDattach lets one channel shares the active geometry
evaluated by pfASD nodes from another channel. Normally, pfASD evaluates
separate active meshes based on each channel that traverses the node. It
automatically ensures that the meshes are consistantly connected between
channels. This is very useful for multiple channels that panel a wall
like shown above. If channels have very different view points, such as in
a multi-player game, then the application should define one pfASD node
for each channel, since the active mesh is going to be very different
from one channel to the other. This is especially important if one
channel is going to have a different evaluation function or a different
LODRange from another, e.g. infra-rad channel and regular channel. pfASD
nodes can share the same raw attribute data, such as pfASDFaces, and
pfASDVerts.
In some applications, one channel would like to display the same geometry
as another channel, e.g. a bird's eye view of the terrain, then this API
should be used to define it. chan0 is the current channel, and chan1 is
the channel that supplies the orginal active mesh. The API can be called
multiple times to define that channel0 shares active meshes from multiple
channels. Example: Define an inset window that looks at the active
geometry generated by master channel traversal.
/* top down view of the active geometry in master Channel */
pfASDattachChan(ViewState->insetChannel, masterChan);
Page 19
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pfChannel::ASDdettach detaches the channel from sharing the active mesh
from another channel.
pfChannel::getAutoAspect returns the aspect ratio matching mode of the
pfChannel.
A pfChannel normally uses its viewing frustum for culling its pfScene (-
pfChannel::setScene). However, a custom culling volume may be specified
by pfChannel::setCullPtope. If non-NULL, ptope identifies a pfPolytope
which is used for scene culling. A copy of ptope, internal to the
pfChannel, is transformed by chan's viewing matrix before culling. If
ptope is NULL, the pfChannel will use its view frustum for culling. A
pfPolytope is a set of half spaces whose intersection defines a convex
volume. Culling performance will be proportional to the number of facets
in ptope. pfChannel::getCullPtope copies the culling polytope of the
pfChannel into ptope. The space argument must be one of the constants
PF_WORLDSPACE or PF_EYESPACE; the culling polytope will be expressed in
the respective coordinate space.
VIDEO CHANNELS
The pfPipeVideoChannel associated with a channel is returned by
pfChannel::getPVChan. In the indexed case, the pfPipeVideoChannel index
is set to num using pfChannel::setPWinPVChanIndex and returned by
pfChannel::getPWinPVChanIndex.
With Dynamic Video Resolution, the actual rendering area (known as the
output viewport) may be smaller than the nominal channel viewport. The
size of the actual viewport area is available from
pfChannel::getOutputViewport where the l, r, b, and t arguments are
pointers to float values that will be updated by the call.
The origin and size of a channel are dynamic under the effect of video
resizing in the same sense. As an example, a viewport whose lower-left
corner is at the center of the pfPipe (with coordinates 0.5, 0.5) would
be changed to an origin of (0.25, 0.25) with respect to the full pfPipe
window if the DVR settings were for scale factors of 0.5 in both X and Y.
The actual rendering origin of a pfChannel is available from
pfChannel::getOutputOrigin with the returned values in the integers
pointed to by xo and yo. The size of a viewport also changes when DVR
scaling is in use, and the actual values are returned by
pfChannel::getOutputSize in the integers pointed to by xs and ys.
When Dynamic Video Resolution is used to alter the rendered size of a
pfChannel, a corresponding change should be made to the width of points
and lines, the two geometry types that support a specific pixel width.
For example, when a channel is scaled in size by on half, lines and
points must be drawn half as wide as well so that when the final image is
enlarged by the inverse scale factor, in this case two, the lines and
points will have the same screen size. pfChannel::setPixScale sets the
indicated channel's pixel scale factor to s. pfChannel::getPixScale
returns this value for the channel.
Page 20
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
Channels also have minimum and maximum pixel scale values, that can be
used to define an acceptable range of pixel scale values. This can be
used to keep lines and points from getting too thin under the effects of
extreme DVR scaling. pfChannel::setMinPixScale sets the minimum
allowable pixel scale value for the channel, and
pfChannel::getMinPixScale gets the value. pfChannel::setMaxPixScale sets
the maximum allowable pixel scale value for the channel, and
pfChannel::getMaxPixScale gets the value.
COMPOSITOR
When developing multi-pipe applications through the use of the
pfCompositor class and related API, the user must not create pfChannels
on compositor-slave-pipes, ie pfPipes which are managed by a pfCompositor
but which are not compositor master pipes.
Each time a pfChannel is created on a master compositor pipe, OpenGL
Performer will automatically create an associated compositor- slave
pfChannel on all slave-pipes of the pfCompositor.
Additionally, most pfChannel methods called on a master-compositor
pfChannel will automatically be propagated to all associated compositor
slaves.
Compositor-related method propagation can be enabled and disabled for
individual pfChannel methods through pfChannel::setCompositorShareMask.
pfChannel::getCompositorShareMask can be used to query which pfChannel
methods will be propagated according to current settings. In both
methods, different PFCOMP_SHARE_* tokens are 'OR-ed' together to express
share mask as a single integer value. See man pfCompositor for a full
list of the PFCOMP_SHARE_* tokens. Note that most of these tokens have a
one-to-one correspondance with PFCHAN_* share tokens used by
pfChannel::setShare.
pfChannels managed by pfCompositor objects will generally render to only
a portion of the viewport specified by the application on master
compositor chennel. Consequently, also the frustum atually used for
culling and drawing a composited channel will differ from the (nominal)
frustum specified by application on master compositor channel.
A number of pfChannel methods have a compositor-related counterpart
(another pfChannel method) allowing user to retrieve both 'nominal' and
'actual' pfChannel parameters.
Below is a list of compositor-related method-pairs. For composited
pfChannels, the 'User' versions of these methods will refer to the
pfChannel's frustum as set by the user on compositor's master channel.
The non-User methods instead refer to the actual frustum used for culling
and rendering the pfChannel, as computed the by pfCompositor.
Note that for regular (non-composited) pfChannels, both methods in any of
Page 21
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
the pairs below should yield the same result.
actual frustum nominal frustum
_______________________________________________________________________
getUserFrustType getFrustType
getBaseUserFrust getBaseFrust
getUserAspect getAspect
getUserFOV getFOV
getUserNearFar getNearFar
getUserNear getNear
getUserFar getFar
getUserPtope getPtope
getUserEye getEye
getUserLeftRightBottomTop getLeftRightBottomTop
userContains(const pfVec3& pt) contains(const pfVec3& pt)
userContains(const pfSphere *sphere) contains(const pfSphere *sphere)
userContains(const pfBox *box) contains(const pfBox *box)
userContains(const pfCylinder *cyl) contains(const pfCylinder *cyl)
|
CALLIGRAPHIC LIGHT POINTS
If a LightPointBoard has been found and initialized before pfConfig, each
pfPipeVideoChannel is automatically setup with a pfCalligraphic
initialized with the pfPipeVideoChannel screen as the Light Point Board
number, and the Video Channel Id as the output to use for calligraphic
light points. You may change this automatic behavior by setting you own
pfCalligraphic on the pfPipeVideoChannel (see
pfPipeVideoChannel::setCallig).
It is also possible to specify a pfCalligraphic per channel using
pfChannel::setCallig and pfChannel::getCallig get the value that has been
set. pfChannel::getCurCallig get the pfCalligraphic that is used for
this pfChannel. If a pfCalligraphic has been set then this value is
returned, otherwise the pfCalligraphic set in the pfPipeVideoChannel is
returned.
The lightpoint board is connected to the SwapReady signal to be
synchronized with the swapBuffer of the graphic pipe. Usually, the
SwapReady signal is enabled only when more than one pipe is used by an
application, in order to synchronize the swapBuffer of channels
distributed across more than one pipe. However, the signal SwapReady has
to be enabled even in single pipe configuration. Enabling calligraphic
light points on a pfChannel will take care of that by attaching the
pfWindow to a swapBarrier. To enable calligraphic call
pfChannel::setCalligEnable with 1 as enable. pfChannel::getCalligEnable
returns this value. By default calligraphic light points are not enabled,
the returned value is therefore 0.
Page 22
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
PICKING
pfChannel::pick is used for screen to world-space ray intersections on a
pfChannel's scene. This operation is often referred to as picking.
Intersections will only occur with parts of the database that are within
the viewing frustum, and that are enabled for picking intersections. The
return value of pfChannel::pick is the number of successful intersections
with the channel scene according to mode.
picklist is a user-supplied pointer. Upon return, the address of an
array of pointers to pfHit objects is stored there. The pfHit objects
come from an internally maintained pool and are reused on subsequent
calls. Hence, the contents are only valid until the next invocation of
pfChannel::pick in the current process. They should not be deleted by
the application.
The contents of the pfHit object are queried using pfHit::query and
pfHit::mQuery. See the man pages for pfHit and pfNode for a description
of the queries.
mode specifies the behavior of the traversal and type of information that
will be returned from the picking process.
mode is a bitwise OR of tokens. In addition to those tokens that can be
specified to pfNode::isect in the mode field of the pfSegSet, the
following values are also allowed:
PFPK_M_NEAREST
Return the picking intersection closest to the viewpoint.
PFPK_M_ALL
Return all picking intersections.
PFTRAV_LOD_CUR
When traversing pfLODs, select the child to traverse based on
range in the specified channel.
When PFPK_M_ALL is set, picklist will contain all of the successful
picking intersections in order of increasing distance from the viewer
eyepoint. See the pfNode manual page for information on the PFIS_
intersection tokens.
px, py identify a 2-dimensional point in normalized channel screen
coordinates in the range 0.0 to 1.0 (with the lower left corner being
(0.0, 0.0)), that corresponds to the channel location to be used for
picking. This 2-dimensional point is used to create a ray from the
viewer eyepoint through the near clipping plane to intersect with the
channel scene.
radius is the radius of the picking region in normalized channel
coordinates used for the picking of lines. This argument is provided for
coarse picking, and possibly for eventual picking of lines and points
Page 23
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
which is currently not implemented. If radius is non-zero, then the mode
argument must not specify the PFTRAV_IS_PRIM mode.
pfNodePickSetup enables the entire database tree under node for picking
intersections and should be called with a pointer to the pfChannel's
scene graph. This effectively calls pfNode::setTravMask with
PFIS_SET_PICK. Selective picking can be done by calling
pfNode::setTravMask, setting the traversal to PFTRAV_ISECT and including
PFIS_SET_PICK in the intersection mask for nodes that are to be enabled
for picking intersections. The picking traversal will not continue past
any node that has not been enabled for picking intersections. See the
pfNode::setTravMask manual page for more information on intersection
setup.
pfChannel::isect is identical to pfNode::isect except a pfChannel is
provided for evaluating pfLODs during the intersection traversal. In
addition, mat specifies an initial transform, allowing intersection
traversals to begin at non-root nodes. All line segments in segSet will
be transformed by mat. mat may be NULL if no initial transform is
needed.
EARTH AND SKY
pfChannel::setScene and pfChannel::setESky set the pfScene and pfEarthSky
that the pfChannel will cull and draw. pfChannel::setScene increments
the reference count of scene so that scene must first be removed from the
pfChannel by pfChannel::setScene(NULL) before scene can be deleted with
pfDelete.
pfChannel::getScene and pfChannel::getESky return the current pfScene and
pfEarthSky for the pfChannel.
Example 1: Setting a pfChannel's pfScene.
void
cullFunc(pfChannel *chan, void *data)
{
pfCull();
}
void
drawFunc(pfChannel *chan, void *data)
{
chan->clear();
pfDraw();
}
/* somewhere in application setup phase */
:
/* set channel's scene */
chan->setScene(scene);
Page 24
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
/* bind cull and draw process callbacks */
chan->setTravFunc(PFTRAV_CULL, cullFunc);
chan->setTravFunc(PFTRAV_DRAW, drawFunc);
GEOSTATES
pfChannel::setGState sets the pfChannel's pfGeoState to gstate. If non-
NULL, gstate is loaded before the pfChannel's DRAW callback is invoked.
Specifically, gstate is loaded with pfGeoState::load so that the state
encapsulated by gstate becomes the global state that may be inherited by
other pfGeoStates within the scene graph. The pfGeoState state
inheritance mechanism is described in detail in the pfGeoState man page.
Note that the channel pfGeoState is loaded before any scene pfGeoState so
that state elements in the scene pfGeoState override those in the
channel's pfGeoState. pfChannel::getGState returns the pfGeoState of the
pfChannel.
pfChannel::setGStateTable sets the pfChannel's pfGeoState table to
gstable. If non-NULL, gstable is made the global pfGeoState table with
pfGeoState::applyTable before the pfChannel's DRAW callback is invoked.
Any indexed pfGeoStates, either referenced by a pfScene (-
pfScene::setGStateIndex) or by scene pfGeoSets (pfGeoSet::setGStateIndex)
will be accessed through gstable. Indexed pfGeoStates are useful for
efficiently managing a single database with multiple appearances, e.g., a
normal vs. an infrared view of a scene would utilize 2 pfGeoState
tables, each referencing a different set of pfGeoStates.
STRESS PROCESSING AND LEVEL-OF-DETAIL
OpenGL Performer attempts to maintain the fixed frame rate set with
pfFrameRate by manipulating levels-of-detail (LODs) to reduce graphics
load when rendering time approaches a frame period. At the end of each
frame, OpenGL Performer computes a load metric for each pfChannel based
on the length of time it took to render the pfChannel. Load is simply
the actual rendering time divided by the desired frame interval.
pfChannel::setLODState specifies a global pfLODState to be used for this
channel.
pfChannel::setLODStateList specifies a pfList of pfLODStates to be
indexed into by pfLODs that have specified indexes via
pfLOD::setLODStateIndex. (See pfLOD and pfLODState).
If stress processing is enabled, OpenGL Performer uses the load metric
and a user-defined stress filter to compute a stress value which
multiplies effective LOD ranges (see pfLOD) for the next frame. Stress >
1.0 'pushes out' LOD ranges so that coarser models are drawn and graphics
load is reduced. Stress == 1.0 means the system is not in stress and
LODs are not modified.
Page 25
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pfChannel::setStressFilter sets the stress filter used by the pfChannel.
frac is the fraction of a frame period the pfChannel is expected to take
to render. frac should be 1.0 if only a single pfChannel is drawn on a
pfPipe and should be > 0.0 and < 1.0 for multichannel simulations. frac
allows the application to apportion rendering time amongst multiple
channels so that a channel drawing a complex scene may be allocated more
time than a channel drawing a simple one. pfChannel::getStressFilter
returns the stress filter parameters for the pfChannel.
low and high define a hysteresis band for system load. When load is >=
low and <= high, stress is held constant. When load is < low or > high,
OpenGL Performer will reduce or increase stress respectively until load
stabilizes within the hysteresis band. low should be <= high and they
both should be positive. Stress is computed using the following
algorithm:
/* increase stress when above high load level */
if (load > high)
S[i] = minimum(S[i-1] + scale*load, max);
else
/* decrease stress when below low load level */
if (load < low)
S[i] = maximum(S[i-1] - scale*load, 0.0f);
else
/* stress unchanged when between low and high load levels */
S[i] = S[i-1];
where S[i] == stress for frame i and load = time[i] * frameRate / frac.
By default, scale = 0.0 and max = 1.0 so that stress is disabled. Stress
is clamped to the range [1.0, max].
pfChannels in a channel group may share a stress filter (PFCHAN_STRESS),
and LOD behavior (PFCHAN_LOD) (see pfChannel::attach). It is useful for
pfChannels which draw into adjacent displays to share LOD behavior. In
this case, the LOD multiplier used by all pfChannels in the channel group
is the maximum of each individual pfChannel. This ensures that LOD's
which straddle displays will always be drawn at the same LOD on each
display.
pfChannel::getLoad will return the last computed load for the pfChannel.
The load value is defined as time * frameRate / frac.
The application may choose to not use the default OpenGL Performer stress
filter by calling pfChannel::setStress to explicitly set the stress
value. Stress values set by pfChannel::setStress will override the
default stress values computed by the stress filter shown above.
pfChannel::getStress returns the last computed stress value for the
pfChannel. The individual stress value is returned regardless of
pfChannel attribute sharing (pfChannel::setShare).
Page 26
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
CUSTOMIZING SCENE GRAPH TRAVERSAL
A pfChannel directs two important traversals: cull and draw. In the cull
traversal, the pfChannel defines the viewing frustum that the database is
culled to and also defines other parameters that modify level-of-detail
behavior. When drawing, the pfChannel defines the parameters of the
"camera" which views the scene. In both cases, a pfChannel traverses a
pfScene which is attached to the pfChannel via pfChannel::setScene. A
pfScene is a hierarchy of pfNodes that defines the visual database.
pfChannel::setTravMode sets the traversal mode of the pfChannel. trav
specifies a traversal type and is either PFTRAV_CULL, PFTRAV_DRAW or
PFTRAV_LPOINT, for the culling, drawing and light points traversal
respectively. mode specifies the corresponding traversal mode. The
culling mode is a bitwise OR of:
PFCULL_VIEW
When set, PFCULL_VIEW enables culling to the viewing frustum.
If not set, the entire database will be rendered every frame.
For best drawing performance it is recommended that PFCULL_VIEW
be set. Unless PFCULL_GSET is also set, OpenGL Performer culls
the database only down to the pfGeode level.
PFCULL_SORT
When PFCULL_SORT is set, OpenGL Performer sorts the database
into "bins" which are rendered in a user-specified order. In
addition, geometry within a bin may be sorted by graphics state
like texture or by range for front-to-back or back-to-front
rendering. Unless the cull stage of the OpenGL Performer
pipeline becomes the bottleneck or PFMP_CULLoDRAW mode is used,
PFCULL_SORT should be set for optimal drawing performance.
Further sorting details are described below.
PFCULL_GSET
When PFCULL_GSET is set, OpenGL Performer culls individual
pfGeoSets within pfGeodes. At the expense of some extra
culling time, this can provide a significantly tighter cull
both because of the finer granularity and because pfGeoSet
culling uses bounding boxes rather than bounding spheres.
However, when traversing portions of the scene graph under a
transformation (pfSCS or pfDCS), OpenGL Performer reverts back
to a cull which stops at the pfGeode level.
PFCULL_IGNORE_LSOURCES
When PFCULL_IGNORE_LSOURCES is not set, OpenGL Performer will
traverse all paths in the scene hierarchy which end at a
pfLightSource node before proceeding with the normal cull
traversal (see pfLightSource). This is required for
pfLightSources to illuminate the scene and will ensure that
graphics hardware lighting is properly configured before the
user's draw callback is invoked (see pfChannel::setTravFunc).
If it is set, any pfLightSources in the pfScene will be
ignored.
Page 27
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
The pfLightSource cull traversal obeys all traversal rules such
as node callbacks, traversal masks, transformations (pfSCS and
pfDCS nodes), and selectors (pfSwitch and pfLOD).
PFCULL_PROGRAM
When PFCULL_PROGRAM is set a cull program attached to the
channel is executed for each pfGeoSet during the cull
traversal. See pfCullProgram for more details.
For drawing, mode is either PFDRAW_OFF or PFDRAW_ON. PFDRAW_OFF
essentially turns off chan. No culling or drawing traversal will take
place. Drawing is enabled by default.
When the optional light points process is used, light points
preprocessing and drawing can be disable for a particular channel giving
PFDRAW_OFF for mode. Creating a light points process enable the the
preprocessing for every channel by default.
pfChannel::getTravMode returns the mode corresponding to trav or -1 if
trav is an illegal or unknown traversal type.
The PFTRAV_MULTIPASS traversal mode is only active when the pfChannel's
scene has one or more pfLightSources which use projected texture-type
lighting. See the pfLightSource man page for more details.
By default, culling to the viewing frustum, culling to pfGeoSet bounding
boxes, pfLightSource culling, and sorting is enabled: (PFCULL_VIEW |
PFCULL_GSET | PFCULL_SORT) For convenience, this default bitmask is
provided by the PFCULL_ALL token.
pfChannel::setTravMask sets the pfChannel's drawing mask and is used in
conjunction with pfNode::setTravMask for selective culling and drawing of
scene graphs on a per-pfChannel basis. During the traversal, the bitwise
AND of the traversal mask and the node mask is computed. If the result
is non-zero, the node is culled or drawn as usual. If off (zero), the
behavior is as follows depending on trav:
PFTRAV_CULL
Node is not culled and is considered to be entirely within the
viewing frustum. The cull traversal traverses the node and its
children without any view culling.
PFTRAV_DRAW
Node is completely ignored. Both cull and draw traversals skip
the node and its children. It is therefore ignored by the light
points process.
Node traversal masks are set by pfNode::setTravMask. The default pfNode
and pfChannel masks are 0xffffffff so that a pfChannel culls and draws
all pfNodes.
pfChannel::getTravMask returns the drawing traversal mask for the
Page 28
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
specified pfChannel. trav is either PFTRAV_CULL or PFTRAV_DRAW.
USING BINS
As mentioned above, pfChannels can sort the database for improved image
quality and improved rendering performance. Database sorting consists of
two steps:
1. Partition database into "bins" which are rendered in a
particular order.
2. Sort database within each bin by:
2a. Graphics state, in which case there is no particular rendering
order or,
2b. Range from the eyepoint in which case the database is rendered
either front-to-back or back-to-front.
During the cull traversal, pfGeoSets are placed into the appropriate bin
according to their bin identifier that was set by pfGeoSet::setDrawBin.
If the bin identifier is >= 0, the cull traversal will place that
pfGeoSet into the bin with that identifier. If the bin identifier is < 0,
then the cull traversal will decide in which default bin the pfGeoSet
belongs.
Note that a pfGeoSet will not go in a bin if: - PFCULL_SORT is not set -
the bin has no drawing order set (see pfChannel::setBinOrder) - the
pfGeoSet has no directly attached pfGeoState.
OpenGL Performer provides the following default bins:
PFSORT_OPAQUE_BIN -
Used for opaque geometry.
PFSORT_TRANSP_BIN -
Used for transparent geometry. Transparent geometry is that
which uses PFTR_BLEND_ALPHA type of pfTransparency.
PFTR_MS_ALPHA-type transparency is considered to be opaque for
purposes of binning.
PFSORT_SHADER_BIN -
Used for all shaded geometry: pfGeoSets with an islAppearance.
See man pfGeoSet::setAppearance for more information about
shaders.
Page 29
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
PFSORT_PATCHYFOG_BIN -
Used internally by pfVolFog.
PFSORT_DEFAULT_BIN - Used for unsorted opaque geometry.
In addition, if the light points process is enabled, a special bin
PFSORT_LPSTATE_BIN is created to sort out all pfGeoSets that have a
pfLPointState attached to their pfGeoState. This bin will not be given
directly to the draw process but instead will be preprocessed by
pfLPoint(). The result of the preprocessing is sent to the draw process
through an internal ring display list.
pfChannel::getFreeBin returns the next available bin identifier and
should be used to avoid collisions with previously selected bins and bins
that are used internally by OpenGL Performer. Note that a bin is
considered unsused if no call to pfChannel::setBinOrder has been made.
Bins are often used to group geometry with certain characteristics.
Sometimes it may be desirable for a pfGeoSet to be in several bins. For
this purpose you can create a subbin of two existing bins using function
pfChannel::findSubbin. The parameters are the two parent bins and an
integer value indicating whether the subbin should be created if it does
not exist. The function returns -1 if the bin does not exists (and it
was not supposed to be created) or if any of the parent bins do not
exist. If you need to create a subbin of more than two bins call this
function several times. For example, to create a subbin of bin 5, 6, and
7, you call pfChannel::findSubbin with parameters 5 and 6. Let us assume
that subbin of bin 5 and 6 is bin 8. Then you call pfChannel::findSubbin
again, with parameters 8 and 7 to obtain subbin of bins 5, 6, and 7. It
does not matter in what order you call it because all subbins are
directly linked to their parent root bins (and vice versa), there is no
tree hierarchy. See pfCullProgram for an example of using subbins.
The method pfChannel::findBinParent returns the first parent of bin bin
that is bigger than the value specified as the second parameter. Thus by
calling this method several times (until it returns -1) you can determine
all parents of a bin.
Each root draw bin has a rendering order set by pfChannel::setBinOrder.
If order is < 0, then bin is not ordered at all - pfGeoSets which belong
to bin are not stored in the bin but are rendered immediately. If order
is >=0, it defines the order in which the bin is rendered, 0 == first, 1
== second etc. The order of subbins is determined by the ChildOrderMask
of their parents. This mask can be set by pfChannel:setBinChildOrderMask.
When a subbin is created the mask or all its parents is combined (using
binary OR) as set as a rendering order of the subbin.
By default, the opaque bin rendering order is PFSORT_OPAQUE_BIN_ORDER (0)
and the transparent bin is PFSORT_TRANSP_BIN_ORDER (1) so that
transparent surfaces are rendered after opaque surfaces. It is legal to
Page 30
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
change the rendering order of the default bins and for different bins to
have the same rendering order although the relative order of these bins
is undefined. The order of subbins cannot be changed.
The light point bin has a huge PFSORT_LPSTATE_BIN_ORDER which is an
indicative value telling that the result of the preprocessing will be
drawn after every other geometry. Modifying the order of this bin has no
effect on that behavior.
Normally, pfDraw renders all root bins in the appropriate order. If a
bin has subbins, objects that are not in any subbin of the bin are
rendered first, followed by objects of each subbin.
To avoid drawing subbins multiple times (for each of its parents) it is
recommended to set a flag PFBIN_DONT_DRAW_BY_DEFAULT for those root bins
that share subbins with the default opaque or transparent bin. The bin
flags can be set using pfChannel::setBinFlags.
Individual bins, including subbins, may be rendered with pfDrawBin when
called in the pfChannel's draw callback (see pfChannel::setTravFunc). -1
is a special argument to pfDrawBin that lets you render the default
sceneDisplayList that contains all the objects that did not fall in any
defined bin. Note that this default sceneDisplayList exists only in
PFMP_CULL_DL_DRAW multiprocessing mode. In case of drawing a subbin, all
subbins that have the same parents as a given subbin will be drawn. For
example, consider root bins 5, 6, and 7 and subbins 8 (child of 5 and 6)
and 9 (child of 5, 6, and 7). When pfDrawBin is called with bin 8, bin 9
will be rendered as well.
pfChannel::setBinSort defines how pfGeoSets are sorted within a bin.
sortType is a symbolic token which identifies the sorting method for bin:
PFSORT_NO_SORT
Do not sort the bin. sortOrders is ignored.
PFSORT_FRONT_TO_BACK
Sort the pfGeoSets in the bin in increasing range from the
eyepoint. Range is computed as the distance from the pfChannel
eyepoint to the center of the pfGeoSet's bounding box.
sortOrders is ignored.
PFSORT_BACK_TO_FRONT
Sort the pfGeoSets in the bin in decreasing range from the
eyepoint. Range is computed as the distance from the pfChannel
eyepoint to the center of the pfGeoSet's bounding box.
sortOrders is ignored.
PFSORT_BY_STATE
Sort the pfGeoSets in the bin by graphics state. The pfGeoSets
in bin are first sorted by pfGeoState. Then if sortOrders is
not NULL, the pfGeoSets will be further sorted by the ordered
Page 31
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
list of PFSTATE_* elements in sortOrders. In this case,
sortOrders should consist of a PFSORT_STATE_BGN token followed
by 0 or more PFSTATE_* tokens followed by a PFSORT_STATE_END
token followed by a PFSORT_END token to end the list. The
PFSTATE_* tokens define a sorting hierarchy. The elements in
sortOrders are copied into the pfChannel data structure, so in
this case it is acceptable to pass static or automatic data not
allocated through pfMalloc.
PFSORT_DRAW_ORDER
Sort the pfGeoSets in the bin directly by their draw order, in
ascending number.
By default, a new bin as a PFSORT_NO_SORT sort order.
Example 1: Sorting configuration example
int sortOrders[PFSORT_MAX_KEYS], i = 0;
sortOrders[i++] = PFSORT_STATE_BGN;
sortOrders[i++] = PFSTATE_FOG;
sortOrders[i++] = PFSTATE_MATERIAL;
sortOrders[i++] = PFSTATE_TEXTURE;
sortOrders[i++] = PFSORT_STATE_END;
sortOrders[i++] = PFSORT_END;
chan->setBinSort(PFSORT_OPAQUE_BIN, PFSORT_BY_STATE, sortOrders);
chan->setBinSort(PFSORT_TRANSP_BIN, PFSORT_BACK_TO_FRONT, NULL);
The default sorting order for the PFSORT_OPAQUE_BIN bin is by pfGeoState
only and the default sorting order for the PFSORT_TRANSP_BIN bin is
PFSORT_BACK_TO_FRONT.
The light points bins sorting is PFSORT_DRAW_ORDER.
Sorting by state is limited to the scope of a transformation (pfDCS or
pfSCS) or a node with draw callbacks, i.e. - pfGeoSets affected by
different transformations or draw callbacks are not sorted together.
However, range sorting spans both transformation and draw callback
boundaries. Thus a range-sorted scene graph with many transformations
and expensive draw callbacks may suffer reduced performance due to an
increased number of transformation and draw callback changes.
If a bin has subbins pfGeoSets are ordered in each subbin separately as
are pfGeoSets that do not belong to any subbin of the bin. A subbin
inherits ordering from a parent with highest sort priority, set by
pfChannel::setBinSortPriority. In case of the transparent bin, the order
in which pfGeoSets are drawn (back-to-front) is important to avoid
visible artifacts and subbins, even if their pfGeoSets were ordered
back-to-front, may break that order. For this purpose, you can mark
selected bins as non-exclusive. If a pfGeoSet belongs to a subbin of a
Page 32
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
non-exclusive bin it is added both to the subbin and directly to the list
of pfGeoSets of the non-exclusive bin. Thus when pfGeoSets of the non-
exclusive bin are sorted they are all in one list. Any root bin can be
marked non-exclusive by setting flag PFBIN_NONEXCLUSIVE_BIN using
pfChannel::setBinFlags. The transparent bin is by default non-exclusive.
Root bins can have draw callbacks associated with them. Draw callbacks
are set by calling function pfChannel::setBinCallBack. The parameters
are: the bin number, the type of a callback (PFBIN_CALLBACK_PRE_DRAW or
PFBIN_CALLBACK_POST_DRAW), and the callback itself. The callback is a
function that has only one parameter, a void pointer that points to the
user data. Each bin has one user data pointer, shared between pre-draw
and post-draw callbacks. This pointer can be set using
pfChannel::setBinUserData. If the callbacks are costly it makes sense to
group subbins of a bin with costly callbacks together. To achieve this
make sure that you set a high child order mask (see above) for the bin.
Subbins are heavily used by cull programs. A cull program allows the user
to specify a sequence of tests, performed during cull traversal, to
decide what bin a pfGeoSet belongs to. More information can be found in
man page for pfCullProgram.
VIEWPOINT AND CAMERA SPECIFICATION
pfChannel::setView specifies both the origin and direction of view for a
pfChannel. xyz specifies the x,y,z position of the viewpoint in world
coordinates and hpr specifies the Euler angles (heading, pitch, and roll)
in degrees of the viewing direction relative to the nominal view (as
defined below). The order of application of these angles is ROTy(roll) *
ROTx(pitch) * ROTz(heading) where ROTa(angle) is a rotation matrix about
world axis a of angle degrees. In all cases a positive rotation is
counterclockwise by the right hand rule. The nominal viewing coordinate
system is +Y = forward, +Z = up, +X = right. For example, a roll of 90
degrees and a heading of -90 degrees would align the view direction with
the +X world axis and the up direction with the -Y world axis.
pfChannel::setViewMat provides another means of specifying view point and
direction. mat is a 4x4 homogeneous matrix which defines the view
coordinate system such that the upper 3x3 submatrix defines the
coordinate system axes and the bottom vector defines the coordinate
system origin. OpenGL Performer defines the view direction to be along
the positive Y axis and the up direction to be the positive Z direction,
e.g., the second row of mat defines the viewing direction and the third
row defines the up direction in world coordinates. mat must be
orthonormal or results are undefined.
The actual viewing direction used for culling and drawing is modified by
the offsets specified by pfChannel::setViewOffsets. The argument xyz
defines a translation from the nominal eyepoint. The Euler angles given
in hpr define an additional rotation of the viewing direction from that
specified by pfChannel::setView and pfChannel::setViewMat. Although this
has similar functionality to pfChannel::setView, it is specifically
Page 33
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
useful for applications which render the same scene into adjacent
displays using multiple pfChannels. Two examples where one would use
pfChannel::setViewOffsets as well as pfChannel::setView are offset-eye
stereo image viewing applications, and for video wall applications.
Example 1: Set up a single pipe, 3-channel simulation using
pfChanViewOffsets.
left = new pfChannel(pfGetPipe(0));
middle = new pfChannel(pfGetPipe(0));
right = new pfChannel(pfGetPipe(0));
/* Form channel group with middle as the "master" */
middle->attach(left);
middle->attach(right);
/* Set FOV of all channels */
middle->makeSimple(45.0f, 45.0f);
middle->setAutoAspect(PFFRUST_CALC_VERT);
/* Set clipping planes of all channels */
middle->setNearFar(1.0f, 2000.0f);
hprOffsets[PF_P] = 0.0f;
hprOffsets[PF_R] = 0.0f;
xyzOffsets->set(0.0f, 0.0f, 0.0f);
/*
* Set up viewport and viewing offsets.
* Note that these are not shared by default.
*/
left->setViewport(0.0f, 1.0f/3.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = 45.0f;
left->setViewOffsets(hprOffsets, xyzOffsets);
middle->setViewport(1.0f/3.0f, 2.0f/3.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = 0.0f;
middle->setViewOffsets(hprOffsets, xyzOffsets);
right->setViewport(2.0f/3.0f, 1.0f, 0.0f, 1.0f);
hprOffsets[PF_H] = -45.0f;
right->setViewOffsets(hprOffsets, xyzOffsets);
Both translation and rotational offsets are encoded in the graphics
library's ModelView matrix. This ensures that fogging is consistent
across multiple, adjacent pfChannels. However, proper lighting requires
a lighting model which specifies a local viewer. Otherwise, geometry
which spans multiple pfChannels will be lit differently on each
pfChannel.
Page 34
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
Example 2: Local viewer lighting model
pfLightModel *lm;
lm = new pfLightModel;
lm->setLocal(1);
lm->apply();
pfChannel::getView copies the view point/direction into xyz and hpr.
pfChannel::getViewMat copies the viewing matrix (without viewing offsets)
into mat.
pfChannel::getViewOffsets copies the view positional and rotational
offsets into the indicated arrays (xyz and hpr).
pfChannel::getOffsetViewMat copies the combined nominal and offset
viewing matrices into mat. This combined viewing matrix is that used for
culling and for configuring the graphics library with the appropriate
transformation. It is defined as offset * nominal where offset is
specified by pfChannel::setViewOffsets and nominal is specified by either
pfChannel::setViewMat or pfChannel::setView.
DRAWING FRAME STATISTICS
OpenGL Performer keeps track of times spent, and operations done, in the
application, cull, and draw stages of the rendering pipeline and
accumulates the data in a pfFrameStats structure. pfChannel::getFStats
is used to get this pfFrameStats structure from the indicated channel.
pfChannel::setStatsMode of the PFCSTATS_DRAW mode selects which of the
enabled statistics classes should be displayed in that channel by
pfChannel::drawStats or pfFrameStats::draw. The statistics are enabled
by pfFrameStats::setClass and the PFCSTATS_DRAW mode is only controlling
the display of statistics that are already enabled.
pfChannel::drawStats or pfFrameStats::draw must be called during each
frame that a statistics display is desired and may be called from any of
OpenGL Performer's application, cull, or draw processes. This manual
page give some pointers on how to interpret the statistics to help in
tuning your database. Refer to the OpenGL Performer Programming Guide
for more detailed information.
pfChannel::setStatsMode selects which of the currently already enabled
statistics through pfFrameStats::setClass, should be drawn. It takes
mode, which is currently just PFCSTATS_DRAW, and the corresponding value
for val, which is a statistics class enabling bitmask. The statistics
classes displayed by pfChannel::drawStats or pfFrameStats::draw are those
statistics classes that have been enabled by pfChannel::setStatsMode for
display, and are also enabled for collection. By default, all enabled
Page 35
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
statistics are displayed.
At the top of the display is the actual frame rate being achieved and the
frame rate set by pfFrameRate and the phase set by pfPhase. If
statistics collection of process frame times has been disabled, then the
actual frame rate will not be known and "???" will be shown. When the
graphics statistics class is enabled for collection, the average number
of pfGeoSets and triangles being displayed is also shown on the top of
the statistics display. See the pfStats::setClass manual page for more
information on enabling statistics classes.
For the Process Frame Times Statistics class, pfChannel::drawStats
displays the amount of time, on average, spent by each process on a
single frame, as well as the number of frames that missed the goal, or
extended beyond the time for the specified goal frame rate. When the
PFFSTATS_PFTIMES_HIST mode is enabled (on by default), a timing diagram
of previous frames is displayed.
Red vertical lines indicate video retrace intervals and green ones
indicate frame boundaries. Horizontal bars indicate the time taken by
pipeline stages. The three different stages: APP, CULL, AND draw are
separated vertically and stages belonging to the same frame are the same
color. Each stage of each frame is labeled with the name of the stage
and its offset from the current frame. For example, the current
application stage is labeled app0 and draw-3 is the draw stage of three
frames back. Stages that are in the same process are connected by thin
vertical lines while stages that are a single process by themselves are
not.
The bar for the application stage is split into a total of six pieces.
The frame starts where the colors change right after a frame boundary
line. Pick up where a new color starts. This will be inside pfFrame and
is where control is given back to the application.
o Post-pfFrame()
The time spent in the application's main loop between the
pfFrame() call and the pfSync() call (highest segment in
application line, drawn as a thick, bright line).
o pfSync() clean and pfApp()
The time spent cleaning the scene graph from application
changes during pfSync(); drawn as mid-hight thick, bright line.
This will also include the time for pfAppFrame() which is
called from pfSync() if not already called for the current
frame by the user. pfSequences are also evaluated as part of
pfAppFrame().
o pfSync() sleep
The time spent sleeping in pfSync() while waiting for the next
field or frame boundary (depending on pfPhase and process
model); the lowest point in the application line, drawn as a
Page 36
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
thin pale dotted line. Typically this wait is for when pfPhase
is PFPHASE_LOCK or PFPHASE_FLOAT. However, note that in
single process with pfPhase of PFPHASE_FREE_RUN, there will be
a sleep period to wait for the swapbuffer of the draw to
complete before continuing with the application since any other
graphics call would effective force such a sleep anyway and in
a place where its timing effect could not be measured.
o Critical Section
The time spent in the application code between calling pfSync()
and calling pfFrame(); drawn as bright raised line. This is the
critical path section and this line should be as small as
possible or non-existent.
o pfFrame() clean
The time spent in pfFrame() cleaning the scene graph after any
changes that might have been made in the previous subsegment,
and then checking intersections; drawn as mid-hight thick
bright line. This line should typically be very small or non-
existent as it is part of the critical path and implies
database changes between pfSync() and pfFrame() which would be
an expensive place to do such changes.
o pfFrame() update
The time spent waiting while the cull and other downstream
process copy updated information from the application and then
starting the downstream stages on the the now-finished frame
(drawn as a low thin line). The end of this line is where
pfFrame() returns and the user main application section (or
post frame section) starts again.
The cull bar is divided into two pieces: first the time spent getting
updates from the application process (slightly raised), and the time
spent culling the scene graph.
The draw timing bar is divided into potentially six pieces:
o Pre-pfDraw()
The time spent in the channel draw callback before the call to
pfDraw() (a very short thick dark raised segment. This will
include the time for your call to pfClearChan(). However, under
normal circumstances, this segment should barely be visible at
all). Operations taking place during this time should only be
latency-critical since they are holding off the draw for the
current frame..
o pfDraw()
The time spent by OpenGL Performer traversing the scene graph
in pfDraw() (drawn as lowered bright thick segment). This
should typically be the largest segment as in the draw line.
Page 37
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
o Post-pfDraw()
The time spent in the channel draw callback after pfDraw()
(another short thick dark raised segment;). On InfiniteReality,
if graphics pipeline timing statistics have been enabled by
specifying PFFSTATS_ENGFXPFTIMES to pfFrameStats::setClass,
this line will include the time to finish the fill for this
channel. Otherwise, it only includes the time for the CPU to
execute and send graphics commands and graphics pipeline
processing from this channel could impact the timing of other
channels.
o Raster LPoint Draw
The time to rendering raster light points computed by a forked
lpoint process. This is drawn as a very raised bright line and
if it exists will be the highest point in the draw line. The
last channel drawn on the pipe will include the time for the
graphics pipeline to finish its drawing. Even if you have no
operations after pfDraw() in you draw callback, this line for
the last channel might look quite long, particularly if you are
very fill-limited and do not have InfiniteReailty graphics
pipeline statistics enabled. It is possible for rendering
calls issued in the previous section to fill up the graphics
FIFO and have calls issued on this section have to wait while
the graphics pipeline processes the commands and FIFO drains,
making the time look longer than expected. If there is no
forked lpoint process, this line will be combined with the
post-draw line of the last pfChannel.
o Draw Stats and Call Swapbuffers
The time spent waiting for the graphics pipeline to finish
drawing the current frame, draw the channel statistics (for all
channels), and make the call to swap color buffers. This is
drawn as apale dotted line. The hardware will complete the
swapbuffers upon the following vertical field or frame line.
The draw timing bar is somewhat inaccurate because the time stamps are
taken from the host and do not reflect when the graphics pipeline
actually finished rendering. Therefore, time for graphics work done in
one part of the draw might be counted in a following part when the
graphics pipeline FIFO filled up and caused the host to wait. This means
that some pfDraw() time could be counted in the following user callback
time, or in the time to draw the statistics. If graphics pipeline timing
statistics are enabled by specifying PFFSTATS_ENGFXPFTIMES to
pfFrameStats::setClass (available on InfiniteReality graphics platforms),
the draw timing line will not have the above inaccuracy as the end time
will be generated by the graphics pipeline when the channel is done
drawing.
If the light process is used its timing bar is added. Like the draw
timing line, the lowest part represent the time actually spent in
pfLPoint() preprocessing the light points; time spend in the user's call
Page 38
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
back routine is in the darkened parts bedore and after. The rendering
time to draw the preprocessed light points is included in the draw timing
bar.
When fill statistics are enabled, the main channel will be painted in
colors ranging from blue to pink that indicate per-pixel depth-
complexity. The brightest (pinkest) areas are those pixels that have
been written many times. The statistics displayed, in green, include
average total depth complexity (total number of pixel writes), as well as
the average, minimum, and maximum number of times a given pixel is
written.
When the Graphics Statistics class is enabled for collection and display,
detailed statistics on numbers of primitives, attributes, state changes,
and matrix transformations are all displayed. These statistics show what
is being drawn by the graphics pipeline. When the
PFSTATS_GFX_TSTRIP_LENGTHS mode is enabled, a histogram of triangle strip
lengths showing the percentage of triangles in the scene in strips of
given lengths is also displayed. For the strip length statistics, quads
are counted as strips of length two and independent triangles are counted
as strips of length one. For graphics performance, it is good to have
much of the database as possible in triangle strips, and making those
triangle strips as long as possible. On a system with RealityEngine
graphics, pay special attention to the numbers for texture loads and
number of bytes loaded. If these numbers are non-zero, then it means
that hardware texture memory is being overflowed and swapped regularly
and this will degrade graphics performance. Both InfiniteReality and
Impact graphics systems are designed to page textures during simulation
and have FIFOS in strategic locations within the hardware pipeline to
support this operation.
The CPU statistics display will show some of the statistics seen in
osview(1). Graphics context switches occur when there are multiple
active graphics windows on the same screen. An application needing high
fixed frame rates should not be encurring graphics context switches.
Another useful indicator of graphics overload is the fifonowait and
fifowait numbers. An excessive number of times seen waiting on the
graphics FIFO could indicate a graphics bottleneck and fill statistics
should be examined. If there are an excessive number of process context
switches, then it might help performance to restrict the draw process to
a single processor and then isolate that processor. OpenGL Performer
will not do this automatically; however, there are utilities in the
OpenGL Performer utility library, libpfutil (see pfuLockCPU), that enable
you to do this. These utilities are demonstrated in the OpenGL Performer
Perfly sample application. These utilities use the IRIX REACT extensions
via sysmp(2).
When the Database Statistics class is enabled for collection and display,
the number of displayed and evaluated nodes for each node type is shown.
When the cull statistics are displayed, a table showing the total number
of nodes and pfGeoSets traversed by the cull process, the number of node
bounding sphere and pfGeoSet bounding boxes tested, and the total number
Page 39
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
of nodes, and pfGeoSets, (of those traversed) that were trivially
rejected as being outside the viewing frustum, the number that were fully
inside the viewing frustum, and the number that intersected the viewing
frustum. The database and culling statistics together can show the
efficiency of the database hierarchy. If many of the nodes in the
database are being traversed by the cull process when only a small
percentage are actually visible, then this indicates that the database
hierarchy is not spatially coherent. If there are many pfGeoSets in each
pfGeode, and many pfGeoSets are being rejected by the cull, then adding
more database hierarchy above current nodes may actually speed up the
culling traversal because cull tests on nodes would be able to accept or
reject large pieces of the database without traversing lower nodes. If
the number of pfLOD nodes evaluated is much more then the number that are
actually drawn, then adding LOD hierarchy might help to reduce the total
number of LOD range calculations, which are fairly expensive.
If there are few nodes in the database relative to the number of
pfGeoSets and the cull is taking a small amount of time but the draw is
taking longer than desired, then adding more nodes and using a database
hierarchy that is spatially coherent should improve the accuracy of the
cull and speed up the draw traversal. If there are only a few pfGeoSets
per pfGeode and the cull is taking longer than the draw in multiprocess
mode, or is taking a significant amount of time in a process shared with
the draw, then it might benefit to not cull down to the pfGeoSet level.
Refer to the pfChannel::setTravMode reference page for information on
setting cull traversal modes.
Graphics load is displayed in the lower portion of the statistics window.
The load hysteresis band (see pfChannel::setStress) is drawn in white and
the previous 3 seconds of graphics load is drawn in red. Load is not
scaled and ranges from 0.0 to 1.0 within the lower portion of the
statistics window.
If stress is active, the display shows a graph of the previous 3 seconds
of stress which is drawn in white. Stress is drawn into the upper
portion and is scaled to fit.
The pfChannel::drawStats display is very useful for debugging and
profiling a particular application and also for visualizing the behavior
of differing multiprocessing modes and pfPipe phases.
OpenGL Performer level-of-detail behavior is primarily dependent on
pfChannel viewing parameters such as view position, field-of-view, and
viewport pixel size. OpenGL Performer assumes that LODs are modeled for
a canonical FOV of 45 degrees and a viewport size of 1024 pixels. OpenGL
Performer computes an internal scale value for pfChannels whose FOV or
viewport size differ from these defaults. This scale value is used to
modify LOD ranges so that correct LOD behavior is maintained. If your
LODs were not modeled with the above defaults you may use PFLOD_SCALE
(see below) to adjust the LOD ranges.
Other LOD modification parameters are set with pfChannel::setLODAttr.
Page 40
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
attr is a symbolic token that specifies which LOD parameter to set and is
one of the following:
PFLOD_SCALE
val multiplies the range computed between chan's eyepoint and
all pfLOD's drawn by the pfChannel. This is used to globally
increase or decrease level of detail on a per-pfChannel basis.
The default LOD scale is 1.0. See the pfLODState and pfLOD man
page for more details.
PFLOD_FADE
val specifies the global fade scale used to fade between levels
of detail. Fade is enabled when val > 0, and is disabled when
val <= 0. Fade is disabled by default. Note that when
computing the actual "fade" or transition distances, this scale
is multiplied by individual fade distance values that are
specified via pfLOD::setTransition. Default pfLOD transition
ranges are 1.0. See the pfLODState and pfLOD man page for more
details.
Performer's LOD fading implementation requires hardware support
for blending using a method other than alpha blending. On
platforms with multisample support, Performer will use
multisample blending for the fading. If there is no multisample
support, Performer will use stipple patterns to do screen door
blending. On platforms where multisample is not present and
stipple patterns are expensive, Performer can not smoothly fade
LOD's.
PFLOD_STRESS_PIX_LIMIT
System stress (pfChannel::setStress) will not affect LOD's
whose projected pixel size exceeds val pixels. This feature is
disabled by default.
PFLOD_FRUST_SCALE
The range multiplier based on the pfChannel's viewport and FOV
is multipled by val. Typically, this feature is enabled with a
value of 1.0 and disabled with a value of 0.0.
LOD fade is useful for avoiding distracting LOD switches. When within
the fade range, LODs are drawn semi-transparent so that adjacent LODs
smoothly blend together. Fade determines the transparency of an two
independent levels of detail. Here is an example for a pfLOD with 3
levels-of-detail and fade range of 30 database units:
Switch Range
0 100 250 350
| | | |
|------------|====|====|-------------|====|====|-----|====|====|
| ^ | ^ | | ^
| | |
| 20/80 LOD0/LOD1 ^ |
Page 41
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
100% LOD0 | 40% LOD2
50/50 LOD1/LOD2
=== indicates where fading is active.
Fade transparency is complementary so that fading the same LOD child with
(fade) and (1.0 - fade) will generate a fully opaque image. As an
example, a fade of 0.7 will cover 70% of the screen area while a fade of
(1.0 - fade) = (1.0 - 0.7) = 0.3 will cover the remaining 30% of the
screen area.
OpenGL Performer ensures that LODs whose switch range is <= 0.0 do not
fade in and also clamps the user-specified fade range to half the
distance between LOD switches. For example, if a pfLOD is specified with
switch ranges 0.0, 100.0, 400.0 and the fade range is 80.0, the result
will be:
Example 2: Fade clamping
Range LOD(s) drawn
---------------------------------------------
0 -> 50 100% LOD0
50 -> 100 100% -> 50% LOD0 + 0% -> 50% LOD1
100 -> 180 50% -> 0% LOD0 + 50% -> 100% LOD1
180 -> 320 100% LOD1
320 -> 400 100% -> 50% LOD1
400 -> 480 50% -> 0% LOD1
Use fade with discretion since it increases rendering time because two
LODs instead of one are drawn when range is within the fade interval.
pfChannel::getLODAttr returns the value of the LOD modification parameter
specified by attr.
OpenGL Performer computes a stress value based on graphics load (-
pfChannel::setStress) to modify LODs. Specifically, when the system
approaches overload, simpler LODs are drawn in order to reduce graphics
load. However, in some situations image fidelity considerations make it
undesirable to draw low levels-of-detail of objects which are close to
the viewer and thus occupy considerable screen space.
PFLOD_STRESS_PIX_LIMIT limits the effects of stress to LODs whose
projected pixel size is less than val. Projected pixel size is based on
the bounding volume of the LOD and is approximate. When val < 0.0, the
stress pixel limit is disabled.
PFLOD_SCALE is a global scale that is useful for debugging and for
adapting LODs modeled at one FOV and viewport size to the canonical FOV
and viewport size used by OpenGL Performer. A val of 0.0 will cause only
Page 42
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
the highest LODs are displayed, since the effective distance will be
uniformly scaled to 0.0.
NOTES
All pfChannels on a pfPipe are rendered into a single graphics window so
that they can share hardware resources such as textures. Additionally,
each channel is rendered in succession rather than in parallel to avoid
costly graphics context switching.
For best performance, channel buffers allocated by
pfChannel::allocChanData should be as small as possible and
pfChannel::passChanData should be called only when necessary to reduce
copying overhead.
When configured as a process separate from the draw, the cull callback
should not invoke OpenGL graphics calls since only the draw process is
attached to a graphics context. However, the display listable libpr
commands invoked in the cull callback will be correctly added to the
current OpenGL Performer libpr display list being built for later
processing by the draw process. Light points process should never invoke
graphics calls as it is separate from the draw process.
Callbacks should not modify the OpenGL Performer database but may use
pfList::get routines to inquire information as desired.
Draw callbacks should not attempt to perform framebuffer swapping
operations directly since OpenGL Performer must control this to handle
frame and channel synchronization. If user control of buffer swapping is
required, register a pfPipe::setSwapFunc callback to cause the named user
written function to be used by OpenGL Performer for swapping buffers.
Sorting back-to-front is required for accurate rendering of
PFTR_BLEND_ALPHA surfaces. The ordering mechanism described above
provides range sorting on a per-pfGeoSet, not a per-triangle basis so
some anomalies may be apparent when rendering transparent surfaces.
These anomalies may be reduced by rejecting back-facing polygons (see
pfCullFace and PFSTATE_CULLFACE).
The OpenGL Performer world coordinate system is +X = East, +Y = North, +Z
= Up and viewing coordinate system is +X = Right, +Y = Forward, +Z = Up.
Note that this is not the same as the OpenGL default coordinate system
which uses +X = Right, +Y = Up, +Z = Out of the screen. OpenGL Performer
internally manages the transformation required to go from a 'Z-up' world
to a 'Y-up' world.
pfChannel::drawStats and pfFrameStats::draw do not actually draw the
diagram but set a flag so that the diagram is drawn just before OpenGL
Performer swaps image buffers.
Drawing the timing diagram does take a small amount of time in the draw
process, so it will perturb the frame rate and timing data to some
degree.
Page 43
pfChannel(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
Fade-based level of detail transition is supported only on RealityEngine
systems and then only when multisampling is enabled.
Octane2 VPro provides a way to improve precision of parameter
interpolation across primitives (especially those primitives which are
large in screen space). For this purpose, Performer running on an Octane2
uses a special purpose cull program which is applied in cull traversal to
detect such primitives (see pfCullProgram for more information about cull
programs). If your application is cull limited, you can disable this
default behavior by setting environment variable GL_VERTEX_PRECLIP. Your
cull will be faster, but your draw will be slower (unless you disable the
detection). The possible values of the environment variable are NICEST
(detects all primitives), FASTEST (faster detection), or DISABLED (no
detection).
BUGS
Intersections, and thus picking, with lines and points is not yet
implemented.
SEE ALSO
pfPipeWindow, pfPipe, pfNode, pfGeoState, pfStats, pfCompositor,
pfConfig, pfCullFace, pfCullProgram, pfDispList, pfEarthSky, pfESkyFog,
pfObject, pfFrame, pfFrameRate, pfFrustum, pfGetSemaArena, pfLightSource,
pfLOD, pfMultipipe, pfMultiprocess, pfPolytope, pfPhase, pfScene,
pfGetSemaArena, pfTransparency, pfuLockCPU
Page 44