Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Occlusion culling with ARB_occlusion_query

  1. #1
    Intern Contributor
    Join Date
    Nov 2011
    Posts
    51

    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.

    Screenshot (UP: without occlusion_query):

  2. #2
    Member Regular Contributor
    Join Date
    Aug 2008
    Posts
    450
    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.

  3. #3
    Intern Contributor
    Join Date
    Nov 2011
    Posts
    51
    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.

  4. #4
    Member Regular Contributor
    Join Date
    Aug 2008
    Posts
    450
    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.

  5. #5
    Intern Contributor
    Join Date
    Nov 2011
    Posts
    51
    Yes, I don't understand why but now it works, but I'm sure I've tested that way already before.
    However thx!

    Question: during async query waits (to get results), what "actions" are allowed meanwhile? gl* functions (glMapBuffer, glReadPixel, and so on) are allowed? or only CPU-side (frustum culling, front_to_back objects sorting, etc...)?

  6. #6
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,128
    You usually use the stall to perform CPU tasks. You might want to check out CHC++ and follow up papers.

  7. #7
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,191
    Quote Originally Posted by thokra View Post
    You usually use the stall to perform CPU tasks. You might want to check out CHC++ and follow up papers.
    Also look at conditional rendering.

  8. #8
    Intern Contributor
    Join Date
    Nov 2011
    Posts
    51
    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.

  9. #9
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,128
    [..]so to implement CHC I would to convert all its source.
    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 ...):

    - Frustum cull your scene
    - Sort visible objects coarsely front to back
    - Render a z-pre-pass (no fragment shading, color masking turned on), maybe just large occluders here, like terrain, large buildings and stuff
    - Enable depth masking (you'll use the depth buffer from the previous step)
    - Render the scene again, this time only the bounding volumes
    - Determine fragments passed and decide whether to render or to cull (partially) occluded objects

    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.

  10. #10
    Intern Contributor
    Join Date
    Nov 2011
    Posts
    51
    Quote Originally Posted by thokra View Post
    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.

    Quote Originally Posted by thokra View Post
    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...
    Last edited by tdname; 10-30-2012 at 03:37 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •