Managing nested glPolygonOffset usage
I have a surprising amount of nested glPolygonOffset usage in my game. I use it for solid wireframing, for decals, for projection of a shadow volume, for drawing the lit pass, etc etc. It's becoming a bit of a pain to manage correctly -- in fact, in twiddling to get output right on NVIDIA and ATI, I've managed to come up with -- at the best -- something which looks mediocre on all hardware ( as in, basically it looks good, but there's a little z-fighting of the shadow volume, and solid wireframing isn't as tight as I'd hope ).
So, I was thinking I might have a global polygon offset manager, of sorts. It seems to me, that I could maintain my own 'factor' and 'units', and add whatever is passed in to the global value, then set glPolygonOffset to that global sum. E.g.
This way, nested calls to change the polygon offset would add up, instead of overriding one another.
Is this a good idea?
Or, conversely, I was thinking I might maintain a stack, where you could push and pop offsets, so once some inner class is done with its drawing, it could pop its offsets and you'd be back to the polygon offset set up by the caller.
Basically, I'm just wondering how you'd robustly manage glPolygonOffset in situations of complex ( and unpredictable ) nesting. Does anybody have any experience here on how best to do this?
So, I was thinking I might have a global polygon offset manager, of sorts. It seems to me, that I could maintain my own 'factor' and 'units', and add whatever is passed in to the global value, then set glPolygonOffset to that global sum. E.g.
Code:
static GLfloat gFactor = 0, gUnits = 0;
void addPolygonOffset( float factor, float units )
{
gFactor += factor;
gUnits += units;
glPolygonOffset( gFactor, gUnits );
}
void resetPolygonOffset( void )
{
gFactor = gUnits = 0;
glPolygonOffset( gFactor, gUnits );
}This way, nested calls to change the polygon offset would add up, instead of overriding one another.
Is this a good idea?
Or, conversely, I was thinking I might maintain a stack, where you could push and pop offsets, so once some inner class is done with its drawing, it could pop its offsets and you'd be back to the polygon offset set up by the caller.
Basically, I'm just wondering how you'd robustly manage glPolygonOffset in situations of complex ( and unpredictable ) nesting. Does anybody have any experience here on how best to do this?
So, in case anybody cares, I implemented a stack-based approach over the weekend, and it works *beautifully*. Just beautifully.
So, for the benefit of anybody who might need this in the future, here's my PolygonOffset class:
First the header:
And now, the implementation:
This works, for me. It solved my problems with nested glPolygonOffset calls.
So, for the benefit of anybody who might need this in the future, here's my PolygonOffset class:
First the header:
Code:
/*
* PolygonOffset.h
* Legion
*
* Created by Shamyl Zakariya on 6/5/05.
* Copyright 2005 Shamyl Zakariya. All rights reserved.
*
*/
#ifndef __POLYGON_OFFSET_H__
#define __POLYGON_OFFSET_H__
#include <map>
#include <vector>
/**
@class PolygonOffset
This is a wrapper for the OpenGL mechanism glPolygonOffset.
PolygonOffset maintains a stack of polygon offsets, such that
deeply nested uses of glPolygonOffset will work cleanly. Imagine,
for example, the situation where you have a solid-wireframed object
being drawn in a multi-pass lighting situation. You'll need to offset
the fill of the solid so the wireframe can be drawn, but since the
object has to be drawn at least twice ( for lighting ) you need differing
offsets for each pass to prevent z-fighting. In a normal usage of
glPolygonOffset one would have to keep track of the current pass
and set offsets accordingly.
But, with the stack-nature of PolygonOffset, one can simply push
an offset, which will be added to the current offset. When done drawing,
one pops the offset ( important, don't forget to pop ).
For reasons of cleanliness, one should never disable GL_POLYGON_OFFSET_FILL
and one should call reset() at the beginning of every drawing loop to
zero the offset.
*/
class PolygonOffset
{
public:
/**
Push an offset -- this will be added to the
current offset. Always call ::pop() when
done drawing with this offset.
*/
static void push( float factor, float units );
/**
Pop the most recently added offset.
*/
static void pop( void );
/**
Resets the offsets to zero and empties the stack.
*/
static void reset( void );
/**
@return the current offset factor
*/
static float currentFactor( void ) { return _currentFactor; }
/**
@return the current offset units
*/
static float currentUnits( void ) { return _currentUnits; }
protected:
PolygonOffset( void ){}
typedef std::pair< float, float > Offset;
typedef std::vector< Offset > OffsetVec;
static OffsetVec _offsetStack;
static float _currentFactor, _currentUnits;
};
#endifAnd now, the implementation:
Code:
/*
* PolygonOffset.cpp
* Legion
*
* Created by Shamyl Zakariya on 6/5/05.
* Copyright 2005 Shamyl Zakariya. All rights reserved.
*
*/
#include "PolygonOffset.h"
#include <GL/glew.h>
/*
typedef std::pair< float, float > Offset;
typedef std::vector< Offset > OffsetVec;
static OffsetVec _offsetStack;
static float _currentFactor, _currentUnits;
*/
PolygonOffset::OffsetVec PolygonOffset::_offsetStack;
float PolygonOffset::_currentFactor = 0;
float PolygonOffset::_currentUnits = 0;
void PolygonOffset::push( float factor, float units )
{
_currentFactor += factor;
_currentUnits += units;
_offsetStack.push_back( Offset( factor, units ));
glPolygonOffset( _currentFactor, _currentUnits );
}
void PolygonOffset::pop( void )
{
Offset offset( _offsetStack.back() );
_currentFactor -= offset.first;
_currentUnits -= offset.second;
_offsetStack.pop_back();
glPolygonOffset( _currentFactor, _currentUnits );
}
void PolygonOffset::reset( void )
{
_offsetStack.clear();
_currentFactor = _currentUnits = 0;
glPolygonOffset( _currentFactor, _currentUnits );
}This works, for me. It solved my problems with nested glPolygonOffset calls.
You have no idea how much you look like an angel to me. It's like you wrote it just for my next project. Massive thanks.
Awesome! Glad to hear it. And, I should have mentioned: don't worry about crediting me or anything, if you need it, use it. I spent all of 10 minutes writing it and 20 migrating my game. Not a biggy.
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Memory usage question | nerman | 3 | 2,600 |
Mar 1, 2006 10:56 AM Last Post: nerman |
|
| Managing framerates, time, and such | Holmes | 7 | 3,710 |
Dec 3, 2002 09:23 PM Last Post: Holmes |
|

