Tutorials
Articles
OpenGL Demos
Games
OpenGL Misc
MSG Board
About
Donate
Links
Home
Megabyte Softworks
C++, OpenGL, Algorithms




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

Download (4.94 MB)
2073 downloads. 64 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.UseProgram();
   spOccluders.SetUniform("matrices.projMatrix", oglControl->GetProjectionMatrix());
   spOccluders.SetUniform("matrices.viewMatrix", cCamera.Look());
   spOccluders.SetUniform("vColor", glm::vec4(1, 0, 0, 0));
   glBindVertexArray(uiVAOOccluders);

   // 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
   glColorMask(falsefalsefalsefalse);
   glDepthMask(GL_FALSE);

   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));

            if(bEnableOcclusionQuery)
            {
               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);
               glEndQuery(GL_SAMPLES_PASSED);
               // 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
                  iSpheresPassed++;
               }
            }
            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
               iSpheresPassed++;
            }
         }
      }
   }

   // Re-enable writing to color buffer and depth buffer
   glColorMask(truetruetruetrue);
   glDepthMask(GL_TRUE);

   // ...
}

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.

Result

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)
2073 downloads. 64 comments
 
Name:

E-mail:
(Optional)
Entry:

Enter the text from image:



Smileys




JosephfiZ (josephgaf@mail.ru) on 02.10.2017 07:21:39
<a href=http://sildenafiloverthecounter30.com/>over the counter sildenafil</a>
over the counter sildenafil
<a href=" http://sildenafiloverthecounter30.com/ ">is sildenafil available over the counter</a>
sildenafil over the counter
Josephpoimb (josephkaw@mail.ru) on 30.09.2017 22:54:11
<a href=http://cialis20mg29.com/>how long does it take for cialis 20mg to work?</a>
cialis 20mg how long does it take to work
<a href=" http://cialis20mg29.com/ ">20mg cialis</a>
splitting 20mg cialis
Dennisantar (dennisgal@mail.ru) on 30.09.2017 20:08:05
<a href=http://cialis5mg29.com/>buy cialis 5mg online</a>
prices for cialis 5mg
<a href=" http://cialis5mg29.com/ ">5mg of cialis</a>
cheap cialis 5mg
Jamessox (jamessexp@mail.ru) on 30.09.2017 19:42:27
<a href=http://cialisforsale29.com/>cialis for sale online in canada</a>
cheap cialis pills for sale
<a href=" http://cialisforsale29.com/ ">discount cialis for sale</a>
real cialis for sale
AlfredNak (alfredvic@mail.ru) on 29.09.2017 21:05:03
<a href=http://viagrasideeffects28.com/>side effects of viagra</a>
adverse side effects of viagra
<a href=" http://viagrasideeffects28.com/ ">viagra side effects cancer</a>
side effects of viagra and alcohol
HerbertIcoff (herbertbof@mail.ru) on 27.09.2017 20:48:09
<a href=http://onlinecasinosforrealmoney12.com/>online casinos for real money no deposit</a>
best online casinos for no real money
<a href=" http://onlinecasinosforrealmoney12.com/ ">what casinos pay for real money online</a>
play for real money online casinos
Fvtjjtounse (vregsdvsdref@aol.com) on 27.09.2017 20:24:06
fast cash payday loan <a href="http://cashadvanceamericasev.org/">cash advance</a> applying for a payday loan [url=http://cashadvanceamericasev.org/]payday loans[/url] ’
DavidPauck (davidrix@mail.ru) on 27.09.2017 19:07:13
<a href=http://winrealmoneyonlineinstantly12.com/>slotland</a>
free slots online
<a href=" http://winrealmoneyonlineinstantly12.com/ ">free casino games</a>
win real money instantly online legit
Rogerlek (rogervox@mail.ru) on 27.09.2017 18:36:33
<a href=http://gambleonline12.com/>best place to gamble online</a>
proctor and gamble online coupons
<a href=" http://gambleonline12.com/ ">gamble online for real money</a>
gamble online usa
Hassanimpef (hassanceaks@mail.ru) on 26.09.2017 03:49:55
english essayanalytical essaywriting paper
essaywriterhow to write an essay <a href=https://lazyessayclub.com/>essay editor</a> conclusion of an essaycreative writing
narrative essay examplescollege essay examplesessay generator
Matthewsnips (matthewtieda@erotraff.top) on 22.09.2017 07:08:15
global pharmacy canada
<a href="http://canadianpharmacyrxbsl.com/">page
</a>
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
Jump to page:
1 2 3 4