Opengl Occlusion queries

Started by
1 comment, last by 21st Century Moose 10 years, 9 months ago

Hello, Ive been working on an Occlusion culler that uses opengl's occlusion queries

although when I render the scene meshes can occlude meshes but when models are in front of each other they still render.

here is the code


void renderer::draw()
{
 for( int m = 0; m < renderer::meshes.size(); m++ )
    {
	 glPushMatrix();
	  if(renderer::meshes[m].yaw != 0 )
	    glRotatef(renderer::meshes[m].yaw,1.0,0.0,0.0);
	  
	  if(renderer::meshes[m].pitch != 0 )		
	    glRotatef(renderer::meshes[m].pitch,0.0,1.0,0.0); 
	  
	  if(renderer::meshes[m].roll != 0 )
	    glRotatef(renderer::meshes[m].roll,0.0,0.0,1.0);
	 
	 if((renderer::meshes[m].scaley != 1)&&(renderer::meshes[m].scaley != 1)&&(renderer::meshes[m].scalez != 1))
	    glScalef(renderer::meshes[m].scaley,renderer::meshes[m].scaley,renderer::meshes[m].scalez);
	 
	 if((renderer::meshes[m].x != 0)&&(renderer::meshes[m].y != 0)&&(renderer::meshes[m].z != 0))	 	
        glTranslatef(renderer::meshes[m].x,renderer::meshes[m].y,renderer::meshes[m].z);	
	 
	 for( int l = 0; l < renderer::meshes[m].trislists.size(); l++ )
        {
         glGenQueriesARB( 1, &renderer::meshes[m].trislists[l].query );
         glBeginQueryARB( GL_SAMPLES_PASSED_ARB, renderer::meshes[m].trislists[l].query);
		 for( int t = 0; t < renderer::meshes[m].trislists[l].tris.size(); t++ )
             {   
              drawtriangle(renderer::meshes[m].trislists[l].tris[t]);
             }
		 glEndQueryARB( GL_SAMPLES_PASSED_ARB );
		}
	 glPopMatrix();
    }
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  
 for( int m = 0; m < renderer::meshes.size(); m++ )
    {
	 for( int l = 0; l < renderer::meshes[m].trislists.size(); l++ )
        {
		 glGetQueryObjectuivARB( renderer::meshes[m].trislists[l].query, GL_QUERY_RESULT_ARB, &renderer::meshes[m].trislists[l].fragmentcount);
		}
    }  
  
for( int m = 0; m < renderer::meshes.size(); m++ )
    {
	 glPushMatrix();
	  if(renderer::meshes[m].yaw != 0 )
	    glRotatef(renderer::meshes[m].yaw,1.0,0.0,0.0);
	  
	  if(renderer::meshes[m].pitch != 0 )		
	    glRotatef(renderer::meshes[m].pitch,0.0,1.0,0.0); 
	  
	  if(renderer::meshes[m].roll != 0 )
	    glRotatef(renderer::meshes[m].roll,0.0,0.0,1.0);
	 
	 if((renderer::meshes[m].scaley != 1)&&(renderer::meshes[m].scaley != 1)&&(renderer::meshes[m].scalez != 1))
	    glScalef(renderer::meshes[m].scaley,renderer::meshes[m].scaley,renderer::meshes[m].scalez);
	 
	 if((renderer::meshes[m].x != 0)&&(renderer::meshes[m].y != 0)&&(renderer::meshes[m].z != 0))	 	
        glTranslatef(renderer::meshes[m].x,renderer::meshes[m].y,renderer::meshes[m].z);	
	 
	 for( int l = 0; l < renderer::meshes[m].trislists.size(); l++ )
        {
		if(renderer::meshes[m].trislists[l].fragmentcount != 0 )
		  {
		   glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
         //draw
         for( int t = 0; t < renderer::meshes[m].trislists[l].tris.size(); t++ )
             {         
              drawtriangle(renderer::meshes[m].trislists[l].tris[t]);
		     }
		   glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
		  }
		  
		  
		}
	 glPopMatrix();
    }

 //clear
 renderer::meshes.clear();
}
Advertisement
I think you misunderstand, what occ queries are. They render the mesh just as if they were disabled. You do not query if they were visible, but rather if any fragments were rendered.If you happen to render your meshes back to front, then every mesh will pass the test, because every mesh renders new fragments. Also, requesting the results of a query can and in your case will stall the gpu, which severely degrades the performance. Even if your code was working, you would still render everything at least once, thus having no gain, and in addition stall the gpu in midframe.

The best advice to give at this point is this: don't use occ queries for occlusion tests, at least not without conditional rendering.

The general way occlusion queries are used is to issue the queries in one frame and read back the results in the next frame; while waiting on a result you use the last known good result, unless the object previously wasn't in the frustum (or is otherwise new to the scene) in which case you must assume that it's visible (until and unless you establish otherwise). That's quite a bit more complex than just begin/draw bounding volume/end/fetch result/draw full mesh depending on result. Obviously it's not going to be as efficient at removing objects as the simpler variant, but it can be expected to run a good deal faster despite that owing to not needing to stall the pipeline.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement