Game Development Community

Occlusion Culling Status

by Dark Tengu · in Torque 3D Professional · 03/14/2013 (11:45 pm) · 27 replies

Several years ago I started a thread about occlusion culling in Torque3D and Tom Spillman had mentioned that it was a priority, does anyone know what happened to that or are we stuck with frustrum culling?
Page «Previous 1 2
#1
03/15/2013 (12:53 am)
I think there's some hardware occlusion culling happening (gpu queries) for certain shapes, and a software occlusion culler for terrain. But I'm not 100% sure.
#2
02/11/2014 (7:25 am)
Stefan
Are you for sure or are you just guessing? I also would like to know the answer to this to. I've been search the forum and haven't found a definite answer..
#3
02/11/2014 (10:04 am)
I've had similar questions raised during my tests as well. From what I can see there is only frustum culling. There's some zone stuff that culls based on the zone instead of the root node, but I'm not seeing any GPU or CPU occlusion culling. There is terrain culling, but it's limited to culling objects blocked by the terrain, not pieces of the actual terrain itself. In my tests this system doesn't always work either.

I've found in my wireframe tests that standing behind a mountain and blocking view has almost no impact on the rendered polys in the scene (minimal at best). I took a look at the code and it seems like "scene/culling/sceneCullingState.cpp" is where most of the magic happens. It's laid out pretty well and commented pretty clearly. I don't think it would be that difficult to jump in there and implement some occlusion culling, we just need to pick a method.

I just finished reading a paper on PLP and cPLP occulusion culling. Here's the paper:
http://www.sci.utah.edu/~csilva/papers/gpg3.pdf

Seems relatively simple, I just hope the benefits outweigh the cost. I think we should opt for a performance-based option and not an accuracy based one like cPLP. I've tried looking for more recent papers but perhaps there hasn't been many improvements made on the methods in the past 13-14 years.

The terrain is still a huge concern of mine, as I feel like even if we have flawless occlusion culling the terrain is still treated as one object and in my tests I see no, or at most negligible, LOD being applied to it ( could be wrong, maybe it just needs adjustments )
#4
02/11/2014 (12:01 pm)
Yes, there are some GPU-side occlusion queries going on for specific objects. I know because now that I've updated to a newer graphics card that fully supports it, I see that water reflections are broken in the Oculus Rift if you set useOcclusionQuery to true. :)

It shows up in WaterObject::renderObject() and ReflectorBase::calcScore(). And unrelated to reflections, a reference in LightFlareData::_testVisibility() as well. I believe there are other uses of the GFX pipeline occlusion query. Start by searching for "occlusionQuery" in the code base.

The whole occlusion query system, CPU and GPU based, could do with a check up.

- Dave
#5
02/11/2014 (1:11 pm)
Found it! GFXOcclusionQuery. All nicely wrapped up and everything. I'm going to play with this and see what I can come up with.
#6
02/11/2014 (4:11 pm)
I decided before I start playing with dx occlusion features I should try a rudimentary proof of concept to make sure I'm digging into the right spot. Here's a quick video identifying the lack of occlusion culling, and my slow and crappy ray cast occlusion. I really didn't tweak it much since it won't be staying.

#7
02/12/2014 (8:32 pm)
Alright, I've got GFXOcclusionQuery working. It's only a first draft so it's completely unoptimized and running the test every single frame on every object (other than player, camera, and global bounds objects) but the scene is using the results from a GFXOcclusionQuery to cull the objects, and I think that's a great start. Obviously I couldn't help but make a video since I'm completely addicted to doing that now:



The biggest bug is it culling objects that shouldn't be culled, though oddly this mainly happens towards the left of the frustum. When I walk to the other side of the boxes the issue isn't there which I find weird. Regardless, by the end I hope to make it rather lenient which is part of the reason why I'm using bounding boxes for the occlusion test. It might cause an oddly shaped thing to render when it shouldn't, but I think it's better than something not rendering when it should, or the user seeing it flicker.

Edit: Not working with advanced lighting turned on. Anyone with knowledge of the advanced lighting system care to shed a light (haha) on what's going on? It's either gotta be something screwing with the depth buffer, or the objects are being drawn again somewhere else.
#8
02/13/2014 (6:35 pm)
I fixed the advanced lighting issue. Advanced lighting floods so many draw calls it backed up the occlusion testing and I was defaulting to drawing the mesh. I've fixed it up to use the previous result until a new result comes in.

It's still in it's infancy but at least it's working. Right now it's performing the test for every object in the scene. I'm going to start by making each scene object able to be flagged to be included in the occlusion test (default to false) and then I'm going to need to come up with a clever way to reduce that list and perform less occlusion tests. Once it start's working the way occlusion should work and there aren't random disappearing objects I'll make a branch for it on github.
#9
02/15/2014 (9:28 pm)
Yeah, so I'm wrong about advanced lighting. It's not working right. Occlusion objects can occlude each other but only when I write them to the depth buffer. As far as I can tell (someone correct the details if I'm off) advanced lighting is a deferred lighting process that uses a geometry buffer (g-buffer) and therefore there's nothing in the depth buffer to test against. Or, maybe I'm just testing at the wrong time. I don't know yet.

As far as I can tell, unless someone has another idea, I'm going to need to return to my original approach of rendering the scene again on a small texture and use that for occlusion testing. That will need serious optimization.

With all that said, it's currently working pretty great without advanced lighting. I've added it to SceneObject so any object can have OcclusionCulling enabled and be tested. The video can't seem to go above 60fps with fraps, but there's about a 100 FPS difference normally when I walk behind the wall. You can see the sharp decline in polys and draw calls. At least in this case the benefits outweigh the cost, but these are high poly models.

Oh, and I won't be showing wireframe anymore. It took me an embarrassing amount of time to realize that when I switch to wireframe the objects aren't occluded anymore and therefore draw again. It only worked before because I was mistakenly writing to the depth buffer so occlusion tests were occluding occlusion tests.

#10
02/16/2014 (5:02 pm)
great work..it would be awesome to see it in adv lighting!
#11
02/17/2014 (4:36 pm)


I reworked it to do it's testing right after the advanced lighting prepass and it seems to be working with advanced lighting now. Thanks to Luis and az from IRC for their efforts. It's not perfect, you can see the cube flicker for a second, so I need to fix a few bugs and then I'm going to add a few attempts at filtering the list of objects that are being tested and only use the GPU occlusion testing on objects that I can't confirm are visible using cheaper methods.

I'm going to take a little break and work on PhysX 3.3 and I'll come back to this in a day or two.
#12
02/18/2014 (8:01 am)
@Andrew..I think you mentioned that you occlusion culling work on all objects?
Would that include TSShapes; or imported DAE files too?
Also do you have a repo I could test from?

Thanks
#13
02/18/2014 (12:41 pm)
I tried to solve as many issues as I can and clean the code up a bit. Here's an initial draft:

github.com/andr3wmac/Torque3D/tree/occlusion_culling

How to test it:

Make a new project, open up a blank scene and add a character model to the scene ( as a TSStatic ) then use the sketch tool to draw a wall blocking the character. You'll probably want to go into the GUI editor and add a few text labels that show the following variables: $fps::real , $GFXDeviceStatistics::polyCount , $GFXDeviceStatistics::drawCalls . Now run the scene and block the character with the wall. My stats:

FPS: ~212.5, Polys: 82058, Draw Calls: 66.

Now, reopen the world editor and inspect the TSStatic. Look down the list of options and you'll see a Culling group with occlusionCulling in it. Check that off, then run the scene again. My new stats:

FPS: ~273, Polys: 27634, Draw Calls: 54

Known Issues:

  1. When you exit the application there's an access violation. This just started happening when I moved the code over to a new project so clearly I missed something. I'll find it later.
  2. Shadows get culled too.
  3. No longer works with Basic Lighting, I can fix this pretty easily later, I just wanted to focus on Advanced Lighting for now since it's more difficult.

If you want to try putting it into a project the only classes I changed are sceneObject and sceneCullingState.
#14
02/21/2014 (6:26 am)
thanks checking it now!
#15
02/21/2014 (10:50 pm)
@Andrew: This is pretty cool. I am busy testing it in my one project now.

Just to confirm, the files you have touched in the engine are:
  • scene/sceneObject.cpp
  • scene/sceneObject.h
  • scene/culling/sceneCullingState.cpp
  • scene/culling/sceneCullingState.h

  • I will update you with my status as well as a few screenies of the fruits of your labour. :)
    #16
    02/22/2014 (9:17 am)
    Correct. Those are the only files altered. Keep in mind when using it there's no optimizations on whether or not it does an occlusion test yet. All objects with it enabled will be tested each frame.

    If it's enabled on a lot of low poly single material objects you won't see a performance increase because you're trading a draw call for a draw call and in the event these objects are visible you're doubling the draw calls by doing the test. In the future objects will be grouped for testing and/or filtered by the CPU to minimize the amount of draw calls used for occlusion testing.
    #17
    02/22/2014 (9:42 am)
    It worked well ... reduced my Draw Calls by half ... but the culling was a little too aggressive.

    Basically if you move the object to the edge of the screen so that only a portion is seen ... it gets culled ... which gives you a strange effect of objects kind of disappearing and appearing in front of you.

    Probably need to push the frustum up ... not sure as my culling knowledge is a little limited ... so I stand under correction.
    #18
    02/22/2014 (10:04 am)
    That's great news! At this point it's more sloppy than aggressive but the end result is the same, things get culled or not culled too early/late. For speed I'm actually just using the bounding box of the object, which I've noticed isn't always accurate. For instance with the player objects it tends to be a little too small causing them to disappear before they're fully occluded. This should be switched to collision geometry or something more accurate in the future. Also, I'll add a debug render for occlusion culling testing so you can see the volumes that are being tested, it really sheds a light on why things are behaving the way they are.

    All and all though, I'm happy to hear it worked for you. I'll continue working on it and building off results from peoples tests and hopefully in a month or two we'll have fully functional occlusion culling :D
    #19
    02/22/2014 (10:21 am)
    Ahhhh ... bounding box ... that explains it. Let me go back and check my bounding boxes ... I think some of them may be invalid or non-existant. 8-}

    Let me know if there is anything I can help with ... this is turning out to be a very valuable improvement to T3D.

    Thank you for your efforts ... it is greatly appreciated. 8-}
    #20
    02/22/2014 (2:46 pm)
    Andrew,
    Yes it worked for me as well..
    I have a scene half culled and my scene drawcalls were 17k before (I know way too high)
    And half culled it reduced my bad scene down to like 9k - 7k average. At some point even dropping to 3k..So it work pretty good, though I agree it is a bit aggressive, but I'm just happy to have it :)

    Thanks for your hard work!
    Page «Previous 1 2