gl errors with occlusion queries
I'm using occlusion queries to modulate the brightness of the sun in my engine. It looks and works great. Now, for purposes of correctness, I use two occlusion queries, one to see how many fragments *would* pass ( drawn with color and depth buffers masked, and depth test turned off ) and the second drawn normally. I get a ratio of the two to modulate my glare.
I just ran my app under GL profiler to try to track down a bug elswhere and I see that I'm getting a GL_INVALID_OPERATION on my occlusion tests. The spec says:
I have to assume one of these is my problem, but I'm not certain how to work around it. I was under the operation that any number of occlusion queries could be run simultaneously...
Here's my code:
I get the GL_INVALID_OPERATION in the last method above, on the line:
And here's the code that creates the query objects:
As far as I can tell, I'm doing the right thing. I've got two query objects, and I only run one at a time.
Any ideas?
I just ran my app under GL profiler to try to track down a bug elswhere and I see that I'm getting a GL_INVALID_OPERATION on my occlusion tests. The spec says:
Code:
The error INVALID_OPERATION is generated if GetQueryObjectivARB or
GetQueryObjectuivARB is called where <id> is not the name of a query
object.
The error INVALID_OPERATION is generated if GetQueryObjectivARB or
GetQueryObjectuivARB is called where <id> is the name of a currently
active query object.
The error INVALID_ENUM is generated if GetQueryObjectivARB or
GetQueryObjectuivARB is called where <pname> is not QUERY_RESULT_ARB
or QUERY_RESULT_AVAILABLE_ARB.I have to assume one of these is my problem, but I'm not certain how to work around it. I was under the operation that any number of occlusion queries could be run simultaneously...
Here's my code:
Code:
void CelestialBody::displayHaloOcclusionQueryTest( void )
{
Camera *camera = world()->activeCamera();
if ( !camera ) return;
/*
The dot-product approaches 1.0 as the camera faces the body.
*/
float d = camera->looking() * _dir,
radius = sinf( _haloArcSize * DEG2RAD ) * camera->farPlane();
/*
No point going further if we're facing away
*/
if ( d < EPSILON ) return;
float size = d * d * radius,
alpha = d;
/*
Read result from last frame's occlusion query.
Then, perform a new occlusion query,
and then draw our halo.
Queries will be one frame old, but who's going to notice?
*/
readOcclusionQueryResult();
performOcclusionQuery();
/*
Use the result from the last occlusion query to
modulate out halo.
*/
alpha = clamp( _occlusionQueryResult * alpha, 0.0f, 1.0f );
displayHalo( camera, size, alpha, false );
}
void CelestialBody::performOcclusionQuery( void )
{
Camera *camera = world()->activeCamera();
float distance = camera->farPlane(),
size = sinf( _arcSize * DEG2RAD ) * distance;
vec3 pos( camera->position() + (_dir * distance )),
up, right, down, left;
camera->billboardVectors( up, right, down, left );
right *= size;
up *= size;
left *= size;
down *= size;
vec3 ll( pos + left + down ),
lr( pos + right + down ),
ur( pos + right + up ),
ul( pos + left + up );
glActiveTextureARB( GL_TEXTURE0_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glColor4f( 0,0,0,1 );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask( GL_FALSE );
/*
Run first query to see how many fragments *would* pass.
To do this turn off depth test.
*/
glDisable( GL_DEPTH_TEST );
glBeginQuery( GL_SAMPLES_PASSED, _queryIDs[0] );
glBegin( GL_QUADS );
glVertex3fv( ll.v );
glVertex3fv( lr.v );
glVertex3fv( ur.v );
glVertex3fv( ul.v );
glEnd();
glEndQuery( GL_SAMPLES_PASSED );
/*
Run second query to see how many fragments *did* pass,
by turning depth test back on.
*/
glEnable( GL_DEPTH_TEST );
glBeginQuery( GL_SAMPLES_PASSED, _queryIDs[1] );
glBegin( GL_QUADS );
glVertex3fv( ll.v );
glVertex3fv( lr.v );
glVertex3fv( ur.v );
glVertex3fv( ul.v );
glEnd();
glEndQuery( GL_SAMPLES_PASSED );
glEnable( GL_TEXTURE_2D );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
}
void CelestialBody::readOcclusionQueryResult( void )
{
GLint fragmentsThatShouldPass = 0, fragmentsThatDidPass = 0;
// !!! GL_INVALID_OPERATION thrown here...
glGetQueryObjectivARB( _queryIDs[0], GL_QUERY_RESULT, &fragmentsThatShouldPass );
glGetQueryObjectivARB( _queryIDs[1], GL_QUERY_RESULT, &fragmentsThatDidPass );
if ( fragmentsThatShouldPass == 0 ) _occlusionQueryResult = 0.0f;
else _occlusionQueryResult = (float) fragmentsThatDidPass / (float) fragmentsThatShouldPass;
}I get the GL_INVALID_OPERATION in the last method above, on the line:
Code:
// !!! GL_INVALID_OPERATION thrown here...
glGetQueryObjectivARB( _queryIDs[0], GL_QUERY_RESULT, &fragmentsThatShouldPass );And here's the code that creates the query objects:
Code:
void CelestialBody::setUseOcclusionQuery( bool oq )
{
/*
Determine if occlusion querying is available, and if
it's real.
*/
_occlusionQueryAvailable = GLEW_ARB_occlusion_query;
if ( _occlusionQueryAvailable )
{
GLint queryCounterBits = 0;
glGetQueryiv(GL_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS, &queryCounterBits);
if ( queryCounterBits == 0 )
{
_occlusionQueryAvailable = false;
}
}
if ( !_occlusionQueryAvailable )
{
using namespace PANSICore;
Logger::log( LogEntry::Debug, "CelestialBody::setUseOcclusionQuery",
"OcclusionQuery is not available, using ray testing." );
oq = false;
}
if ( oq )
{
Ray_Delete( _ray );
_ray = NULL;
if ( !_queryIDs[0] )
{
glGenQueriesARB( 2, _queryIDs );
}
setRequiresStepping( false );
}
else
{
if ( !_ray )
{
_ray = new Ray( this );
}
if ( _queryIDs[0] )
{
glDeleteQueriesARB( 2, _queryIDs );
_queryIDs[0] = 0;
_queryIDs[1] = 0;
}
/*
Need to be stepped to update the ray
*/
setRequiresStepping( true );
}
}As far as I can tell, I'm doing the right thing. I've got two query objects, and I only run one at a time.
Any ideas?
UPDATE:
I changed my code which performs the query to check if the results are available ( as well as wether the query object names are valid ) and I still get the error, just now it's on the call to GL_QUERY_RESULT_AVAILABLE.
What's even more baffling is that if I tell Profiler to continue -- past the breaks on error -- once the first frame is done rendering it works fine.
Baffling!
I changed my code which performs the query to check if the results are available ( as well as wether the query object names are valid ) and I still get the error, just now it's on the call to GL_QUERY_RESULT_AVAILABLE.
What's even more baffling is that if I tell Profiler to continue -- past the breaks on error -- once the first frame is done rendering it works fine.
Baffling!
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| 2D Pixel Collision Detection using OCCLUSION | Elphaba | 0 | 2,969 |
Jun 8, 2009 06:30 AM Last Post: Elphaba |
|
| Occlusion query code failing on ATI 9600 | TomorrowPlusX | 4 | 4,709 |
Mar 10, 2007 08:52 AM Last Post: arekkusu |
|
| Occlusion query failing for fogged occluders | TomorrowPlusX | 12 | 5,604 |
Jan 8, 2006 05:03 PM Last Post: arekkusu |
|
| Occlusion queries... SLOW. | TomorrowPlusX | 8 | 4,035 |
Aug 19, 2005 07:05 AM Last Post: TomorrowPlusX |
|

