OpenGL Demos
OpenGL Misc
MSG Board
Megabyte Softworks
C++, OpenGL, Algorithms

Current series: OpenGL 3.3
(Return to list of OpenGL 3.3 tutorials)

Download (4.94 MB)
2198 downloads. 74 comments
27.) Occlusion Query

Hello guys! This is the 27th tutorial from my series. This one is about occlusion query, which is used to speed up rendering and discard rendering some complex geometry, that won't be rendered simply because it cannot be visible in scene for sure. The principle is really simple - before rendering any complex geometry of the object with many meshes and triangles, we first render a simple bounding shape of an object (for example, bounding box is the easiest) and we just ask OpenGL, whether we would have successfully rendered any fragments (pixels). If rendering of a bounding box wouldn't make a change to a framebuffer (i.e. it's not visible in scene at all), that means, that the object itself cannot be visible as well and we can discard rendering the whole complex shape! And that's the whole simple point, coding it won't be very difficult, so let's dig deeper into it .

Occlusion Query

The whole process described above is called an occlusion query. Unfortunately, the translation of the words occlusion, occluder and occludee doesn't exist in Slovak language, so I hope I won't misuse them (if yes, let me know) . Occluder is in our case the bounding box, because it occludes (contains, consumes ) the object we are testing - the occludee (the highly tesselated sphere in our case). That means that we are not going to actually render occluder, but only ask if it were rendered if we actually rendered it (if we would see some of its parts). If we could see at least one pixel of it, some parts or maybe whole occludee (highly tesselated sphere) is probably visible too and thus we will render it. The whole rendering code is here and I will explain it line by line:

bool bShowOccluders = false;
bool bEnableOcclusionQuery = true;

void RenderScene(LPVOID lpParam)
   // ...

   int iSpheresPassed = 0;
   bool bRenderSphere[3][3][3];
   glm::mat4 mModelMatrices[3][3][3];

   spOccluders.SetUniform("matrices.projMatrix", oglControl->GetProjectionMatrix());
   spOccluders.SetUniform("matrices.viewMatrix", cCamera.Look());
   spOccluders.SetUniform("vColor", glm::vec4(1, 0, 0, 0));

   // Occlusion query begins here
   // First of all, disable writing to the color buffer and depth buffer. We just wanna check if they would be rendered, not actually render them

   FOR(x, 3)
      FOR(y, 3)
         FOR(z, 3)
            bRenderSphere[x][y][z] = false;
            float fLocalRotAngle = fGlobalAngle + x*60.0f + y*20.0f + z*6.0f;
            glm::vec3 vOcclusionCubePos = glm::vec3(-fCubeHalfSize+fCubeHalfSize*x*2.0f/3.0f + fCubeHalfSize/3.0f, -fCubeHalfSize+fCubeHalfSize*y*2.0f/3.0f + fCubeHalfSize/3.0f, -fCubeHalfSize+fCubeHalfSize*z*2.0f/3.0f + fCubeHalfSize/3.0f);

            mModelMatrices[x][y][z] = glm::translate(glm::mat4(1.0), glm::vec3(0.0f, fCubeHalfSize, 0.0f));
            mModelMatrices[x][y][z] = glm::translate(mModelMatrices[x][y][z], vOcclusionCubePos);
            mModelMatrices[x][y][z] = glm::rotate(mModelMatrices[x][y][z], fLocalRotAngle, glm::vec3(1, 0, 0));
            mModelMatrices[x][y][z] = glm::rotate(mModelMatrices[x][y][z], fLocalRotAngle, glm::vec3(0, 1, 0));
            mModelMatrices[x][y][z] = glm::rotate(mModelMatrices[x][y][z], fLocalRotAngle, glm::vec3(0, 0, 1));

               mModel = glm::scale(mModelMatrices[x][y][z], glm::vec3(fCubeHalfSize/3, fCubeHalfSize/3, fCubeHalfSize/3));
               spOccluders.SetUniform("matrices.modelMatrix", mModel);

               // Begin occlusion query
               glBeginQuery(GL_SAMPLES_PASSED, uiOcclusionQuery);
                  // Every pixel that passes the depth test now gets added to the result
                  glDrawArrays(GL_TRIANGLES, 0, 36);
               // Now get tthe number of pixels passed
               int iSamplesPassed = 0;
               glGetQueryObjectiv(uiOcclusionQuery, GL_QUERY_RESULT, &iSamplesPassed);
               // If some samples passed, this means, that we should better render the whole sphere, because we were able
               // to see its bounding box
               if(iSamplesPassed > 0)
                  bRenderSphere[x][y][z] = true;
                  // Increase the number of spheres that have passed
            else // If we do not use occlusion query, then all of the spheres have passed
               bRenderSphere[x][y][z] = true;
               // Increase the number of spheres that have passed

   // Re-enable writing to color buffer and depth buffer

   // ...

So what we're basically doing here is that we have an 3x3x3 array of booleans, where we store true or false - whether to render particular sphere or not. First of all, we must disable writing to color and depth buffer using glColorDepthMask and glDepthMask. That means, that anything that is rendered now (our occluder) will actually not get written into any of the buffer and thus not get rendered. But thanks to occlusion query, we can ask that important question - how many fragments (pixels) have passed the depth test and made it to the final stage of rendering, i.e. writing to color buffer? To start the occlusion query, we must first call the function glBeginQuery(GL_SAMPLES_PASSED, uiOcclusionQuery). This function has two parameters - first is query type, in our case it is GL_SAMPLES_PASSED - we would like to find how many fragments will make it to the rendering phase. The second parameter is query object - to run a query, you must have an OpenGL generated ID associated with it. This is done in the initScene() using the glGenQueries function, which we have also used in the 23rd tutorial about Particle System, where queries have been used for figuring out number of output primitives.

Now that we have began the GL_SAMPLES_PASSED query and have turned off writing to color and depth buffer, every pixel that would make it through counts. So now we just render the bounding box of the sphere and then call the glEndQuery function, which as the name suggests ends the query. Note that we have separate shader program for bounding box rendering without any texturing and lighting calculations, just a flat fragment output, because this is the only thing we care about at the moment. Now we are able to ask for the result of the query - number of pixels passed. This is done using glGetQueryObjectiv(uiOcclusionQuery, GL_QUERY_RESULT, &iSamplesPassed) function and now iSamplesPassed holds the number of pixels passed. Only if this number is greater than zero, only then we want to render the sphere. We mark it to our array of booleans and proceed to next sphere.

When we are done testing which spheres should be rendered, next steps is naturally to render (possibly) visible spheres. We just need to re-enable writing to depth and color buffer and then go through every sphere in the scene using the data from previously filled array of booleans. And that's it .

NOTE: There also exists a query GL_ANY_SAMPLES_PASSED, result of which is GL_TRUE or GL_FALSE, if any pixels have passed or none at all, respectively. This query would also work in this case, but I tested it and I didn't find any performance-wise speed-up, so I sticked with GL_SAMPLES_PASSED with comparing it against 0. You can try it out yourself .

When To Use Occlusion Query

Occlusion query is really nice and simple way to get rid of objects not present on the scene easily. But I found out, that it should be used in cases, when we are rendering really really complex objects only. I mean that there is a certain threshold, starting from which it's worth using. For example - if we used sphere with 10 stacks and 10 slices only, the occlusion query (at least on my computer) resulted in lower FPS than without it. However with spheres with 200 stacks and 200 slices, the FPS difference was remarkable when rendering with or without occlusion query. In such cases, the occlusion query really paid off. You can actually test it in the application by turning occlusion query ON / OFF and also by modifying stacks and slices numbers of a single sphere in sphere.ini file, which is present in the bin directory (where exe is). So you can try to modify this value and see the results for yourself.


This is the fruit of today's effort:

I think that this tutorial was one of the easiest I have ever written. It's really not difficult to understand logic behind it, nor is it difficult to convert it to code. I recommend you to play a little with that stacks / slices parameter to see the FPS differences. Next time I will probably create a little more complex tutorial, as this one was really chill .

Download (4.94 MB)
2198 downloads. 74 comments


Enter the text from image:


Matthewsnips (matthewtieda@erotraff.top) on 22.09.2017 07:08:15
global pharmacy canada
<a href="http://canadianpharmacyrxbsl.com/">page
global pharmacy canada
<a href=http://canadianpharmacyrxbsl.com/?kamagra-shop>kamagra shop</a>
walmart pharmacy price check
<a href="http://canadianpharmacyrxbsl.com/?what-is-cialis">what is cialis</a>
Matthewsnips (matthewtieda@erotraff.top) on 21.09.2017 21:35:50
buying drugs canada
<a href="http://canadianpharmacyrxbsl.com/">canadian online pharmacies</a>
online pharmacy canada
<a href=http://canadianpharmacyrxbsl.com/?list-of-reputable-canadian-pharmacies>list of reputable canadian pharmacies</a>
canadian pharmacy no prescription needed
<a href="http://canadianpharmacyrxbsl.com/?xanax-generic-name">xanax generic name</a>
WayneQuade (waynerarie@mail.ru) on 13.09.2017 11:18:51
<a href=http://howtowinmoneyonline12.com/>how to win real money online for free</a>
how to win big money online
<a href=" http://howtowinmoneyonline12.com/ ">how to win money online casino</a>
how to win money online for free with games
Charlestulge (charlespurgy@mail.ru) on 13.09.2017 07:41:34
<a href=http://playgamesformoney12.com/>play free casino games for real money</a>
play online games for money
<a href=" http://playgamesformoney12.com/ ">play games for money and prizes free</a>
play games for money no deposit
Jamesbor (jameswex@mail.ru) on 13.09.2017 07:41:33
<a href=http://goldennuggetonline12.com/>golden nugget poker online</a>
golden nugget online casino
<a href=" http://goldennuggetonline12.com/ ">golden nugget online</a>
golden nugget casino online
HowardBub (howardvelve@mail.ru) on 13.09.2017 06:59:09
<a href=http://casinolive12.com/>maryland live casino poker</a>
hotels close to maryland live casino
<a href=" http://casinolive12.com/ ">maryland live casino jobs</a>
live social casino
JosephBes (josephdousa@mail.ru) on 10.09.2017 21:01:46
<a href=http://howmuchdoescialiscost5.com/>cialis cost walmart</a>
cialis cost
<a href=" http://howmuchdoescialiscost5.com/ ">cialis cost per pill</a>
how much does cialis cost
AntonioCaunk (antonioomilk@mail.ru) on 10.09.2017 17:57:27
<a href=http://orderviagra04.com/>viagra order online</a>
can you order viagra online
<a href=" http://orderviagra04.com/ ">phone number to order viagra</a>
how to order viagra online
ErnestPhign (ernestbiace@mail.ru) on 10.09.2017 17:04:33
<a href=http://viagraforsale7.com/>viagra for sale online usa</a>
viagra or cialis for sale
<a href=" http://viagraforsale7.com/ ">viagra pills for sale</a>
cheap viagra pills for sale
AnthonyAtown (anthonyagick@mail.ru) on 09.09.2017 10:13:42
<a href=http://buyantabuse8.com/>buy antabuse online no prescription</a>
buy antabuse online
<a href=" http://buyantabuse8.com/ ">buy antabuse canada</a>
buy antabuse online cheap
Jaredmap (jaredurips@mail.ru) on 08.09.2017 06:52:37
<a href=http://clomidforsale7.com/>fertility drugs clomid for sale</a>
clomid for sale amazon
<a href=" http://clomidforsale7.com/ ">clomid for sale no prescription</a>
clomid for sale for women
JosephHaf (josephemora@mail.ru) on 08.09.2017 06:52:36
<a href=http://ciprofloxacinprice7.com/>ciprofloxacin drops price</a>
ciprofloxacin ear drops price
<a href=" http://ciprofloxacinprice7.com/ ">ciprofloxacin 500mg price in india</a>
ciprofloxacin 500mg tablets price
JamieBooda (jamiebrime@mail.ru) on 08.09.2017 06:45:59
<a href=http://sertralineprice7.com/>sertraline 50 mg price walmart</a>
sertraline price walmart
<a href=" http://sertralineprice7.com/ ">price of sertraline</a>
sertraline price without insurance
WayneFap (waynegling@mail.ru) on 08.09.2017 02:33:39
<a href=http://prednisoneprice7.com/>price of prednisone 10mg</a>
prednisone price walmart
<a href=" http://prednisoneprice7.com/ ">price of prednisone 20 mg</a>
prednisone 20mg price
SteveFully (stevesmath@mail.ru) on 07.09.2017 07:19:31
<a href=http://onlinekasino6.org/>kasino amp</a>
netent kasino
<a href=" http://onlinekasino6.org/ ">online kasino</a>
online kasino
Howardamume (howardswomy@mail.ru) on 07.09.2017 06:42:41
<a href=http://casinoslotmachine6.org/>casino slot machine</a>
free slot machine games casino
<a href=" http://casinoslotmachine6.org/ ">jackpot party casino slot machine</a>
free game slot machine casino
JosephBes (josephdousa@mail.ru) on 06.09.2017 04:46:07
<a href=http://howmuchdoescialiscost5.com/>cost of cialis without insurance</a>
cialis cost at cvs
<a href=" http://howmuchdoescialiscost5.com/ ">how much does cialis cost without insurance</a>
cost of cialis 20mg
JerryInhap (jerrytup@mail.ru) on 06.09.2017 04:43:14
<a href=http://genericviagraonline5.com/>generic viagra</a>
buy generic viagra online
<a href=" http://genericviagraonline5.com/ ">is there a generic for viagra</a>
when will viagra be generic
Jamesmuh (wlufouzkdiwuxyd@mail.ru) on 05.09.2017 04:22:22
<a href=http://purchaseviagra04.com/>viagra purchase in india</a>
purchase viagra online with paypal
<a href=" http://purchaseviagra04.com/ ">free viagra samples without purchase</a>
viagra purchase
Richardcet (richardbrisy@mail.ru) on 05.09.2017 03:06:30
<a href=http://viagraforsale04.com/>viagra for sale</a>
cheap viagra for sale
<a href=" http://viagraforsale04.com/ ">viagra pills for sale</a>
liquid viagra for sale
Jump to page:
1 2 3 4