Occlusion culling with ARB_occlusion_query

I've tried many ways but I can't execute a good occlusion culling using ARB_occlusion_query extension.

- glClear(...)
- BEGIN WHILE for each object....
--- frustum culling check
--- if not in frustum, continue to next object--- I turn off color mask
--- glDisable(GL_CULL_FACE);
--- I render bounding box
--- glEnable(GL_CULL_FACE);
--- check culling result with glGetQueryObjectuiv(...., &occlusion_result)
--- I turn on color mask
--- I render only visible object (visible = "occlusion_result" variable greater than 0)
- END WHILE

Using this way I have boundig_boxes drawn on screen!
How I can "render" without print to screen?
I've already tried to "render" to FBO but it seems not to work using occlusion_query...so I preferred to stay in the default "DRAW_FRAMEBUFFER" which give me some fragment_count greater than zero.

Did you disable writing to the depth buffer too? Otherwise you will get objects that are drawn after the bounding box that fail the depth test when they aren't meant to, including the object that is meant to be contained inside the bounding box.

Nope, depth_test is always enabled...infact the "grey bounding box" (which is not shaded due to colorMask to FALSE) visible in my screenshot is placed well in its right place and moving camera it moves according to the movement.

My problem seems to be just the "bounding box draw" during normal rendering.
All online examples doesn't uses two passes....but in my engine a single pass produces that effect, and it's wrong.

Maybe I could solve the problem with a second pass in this way:
void Render(){
- 1st glClear(color | depth)
- BEGIN WHILE for each object
- execute occlusion query
- save occlusion query result in an object's internal variable
- END WHILE
- 2nd glClear(color | depth)
- BEGIN WHILE for each object
- render only object with previous internal variable to TRUE
- END WHILE
}

But I want to know why I have always problems and I can't use any SIMPLE source code I found online.....I'm a bit angry about that hahahaha
I always have to interpret it or completly rewrite from scratch with a lot of changes.

You have to disable depth writes for your bounding boxes, since you don't want their depth value to be stored in the depth buffer - you only want the box to be tested to see if any values would be visible. Disable depth writing for your bounding box in a similar way to color writing:

Code :

glDepthMask(GL_FALSE);

AFAICT, it isn't the bounding boxes that are being drawn to the color buffer, but the terrain that isn't being drawn in that position due to your bounding box having already written a nearer depth value to the depth buffer, so the sky is visible through it.

CHC seems great but at the moment I have many other things to do, expecially because I don't use C++/VC++ but Delphi, so to implement CHC I would to convert all its source.

However I've got other questions:
- I think OpenGL/Shader needs to know which object is behind other to return Zero as occlusion_query result...but if I disable DepthMask, how can it knows all that?
- Sort objects from front to back: due to DepthMask disabled, each rendered "layer"/object would covers previous one, so FRONT objects (which are drawn for firsts) will be covered from BACK ones (subsequently drawn). In this way back objects will be rendered in "top-layers" leaving FRONT objects covered by them and stay in background. I don't understand this step: disable DepthMask and sort objects...

Now I've got "perfect" render (not like my first screenshot) but all occlusion_query results are greater than Zero even if I have very big cube in front of the camera covering all the scene.
I've tried to temporaly enable ColorMask and/or DepthMask to really render boundingBoxes which are involved during occlusion_queries, but all boxes seems fine....but this big cube in front of the camera seems to not covers nothing while I get queries results.

No you thieve. Just take the paper and implement it yourself - you'll learn more and can tailor your code to your needs while writing and not while porting.

I think OpenGL/Shader needs to know which object is behind other to return Zero as occlusion_query result...but if I disable DepthMask, how can it knows all that?

No. The way occlusion queries work is that the GPU keeps track of how many fragments were actually rasterized and writes the number(or a kind of a boolean with GL_ANY_SAMPLES_PASSED*) into the query object. You can then retrieve the number of samples from the query object with glGetQueryObject(). Disabling the depth mask doesn't mean a depth value used for depth testing isn't generated. It means the depth buffer will not be updated with the depth values. This is especially useful if you render a depth pass first and then do the occlusion culling with depth masking.

Sort objects from front to back: due to DepthMask disabled, each rendered "layer"/object would covers previous one, so FRONT objects (which are drawn for firsts) will be covered from BACK ones (subsequently drawn). In this way back objects will be rendered in "top-layers" leaving FRONT objects covered by them and stay in background. I don't understand this step: disable DepthMask and sort objects...

Here's one way with a depth-first pass (or depth-only pass, or depth pre-pass, or z-pre-pass or ...):

This is not the only way. There are multiple philosophies as to how to occlusion cull a scene in the best possible way. Something much simpler but still maybe worth it is a method by Croteam's Dean Sekulic in GPU Gems.

DICE took a completely different route in their Frostbyte engine. They implement a software rasterizer which renders a coarse depth map of the scene using simplified proxy meshes for considerable occluders and do the culling on the CPU. The same goes for the guys at Guerilla.

GPU keeps track of how many fragments were actually rasterized and writes the number into the query object

Of course. But without your explanation ("disabling the depth mask doesn't mean a depth value used for depth testing isn't generated") queries behaviour was a mystery
Thanks for clarification.

Originally Posted by thokra

Here's one way with a depth-first pass (...)

So your recomend is to do a z-pre-pass (1), occlusion_query pass (2) to get results and finally the rendering one (3)? How many passes......
I know there are many ways and implementation of occlusion culling, but I think the minimum required passes can't be less...so I must surrender to do all those passes?
I'm angry about technology limits...