What is BGE view frustum culling granularity? Planes? Or objects?

As simple as the title says; I would like a definitive answer as to whether the builtin game engine does view frustum culling on the plane level, or the game object level. Or possibly both.

Most of my web searching has suggested that it is done object for object, here’s a most relevant reference in the release logs for 2.34…

This system checks the bounding box area of each object in the scene against the frustum area and only passes objects with overlaping volumes to be rendered.

However, nothing has specifically demonstrated, proved, or expressly stated this as a fact opposed to the alternative. Furthermore, I have done some meager tests with a large object that has a high polly count, and it indeed culls on a plane by plane basis. I have a blend that adequately demonstrates this, but it is over the upload limit.

Unfortunately, I can’t think of a test that demonstrates object based frustum culling. Such would require one be able to watch the object get culled after it left the view frustum, which shouldn’t be possible for obvious reasons.

Anyone care to shed some light on this issue?

It is a bounding box test (per object).

It is simply the cheapest way to do that. The bounding box is calculated from the mesh and the camera’s view

OK, that is in alignment with what I have been reading. I’m still having trouble knowing when this is ever used though.

Say I have large high-poly object, where only a small portion of it is inside the view frustum at any given time (terrain is a good for instance). Would it be good to divide up that object into many smaller game objects, so each part could be bounding box culled?

From what I can tell, each plane of an object is already getting culled when it has left the view frustum, so it shouldn’t reduce the on-screen poly-count to then take away objects that are also outside. I mean, I presume that the bounding box is always slightly larger than the object, thus it’s visible polygons would already be culled before the bounding box leaves the frustum.

Maybe I’m confused… I don’t know.

What I do know is that it’s 5:45AM, I’ve been up all night, and if I have anymore coffee I’M going to get culled.

I’m not sure what you mean by “each plane” of an object. The object has an AABB associated with it, and when it leaves the frustum of the camera (composed of separate planes) it is culled. A large object will be culled only if its large bounding box leaves the frustum. That same object, divided into smaller parts, will yield better rendering performance as it is only partially rendered (of course, in reality the partial rendering is just that we render only certain objects which make up a greater one).

No the single planes are not culled. It is the complete mesh.

This means a large mesh like a terrain gets into the render pipeline even when only a small part is seen.

On the other hand a lot of small objects add to the render time too. so you need to find a balance between mesh size and number of objects.

I’m not sure what you mean by “each plane” of an object.

Sorry, I really meant faces or polygons of the mesh. I have edited the post.

That same object, divided into smaller parts, will yield better rendering performance as it is only partially rendered (of course, in reality the partial rendering is just that we render only certain objects which make up a greater one).

Thank you for this, that’s about what I was expecting. (This is getting added to my bag of tricks to be sure.) :wink:

The object has an AABB associated with it, and when it leaves the frustum of the camera (composed of separate planes) it is culled. A large object will be culled only if its large bounding box leaves the frustum.

Yeah, I’m pretty sure I at least get this part now. Basically, a simplified representation of the object (the AABB) is tested against the frustum. If there is overlap then that object must need to be rendered. Pretty straightforward really.

No the single planes are not culled. It is the complete mesh.

This means a large mesh like a terrain gets into the render pipeline even when only a small part is seen.

Given the above, I’m sure culling is done on complete meshes. However, I am still seeing single polygons of a render object disappear when they pass beyond the far plane of the view frustum.

You can see this yourself. Make a long cylinder, give it many planes. Set up a camera with basic motion. Run the BGE and move the camera along the axis of the cylinder. When the end of the cylinder gets far enough from the camera, polygons will start to disappear, but the object as a whole will remain.

Surely this is some form of polygon level culling? (and it’s not related to backface culling, these polygons still face the camera.) Culling on the front and back of the frustum maybe as simple as a Z-depth test, but I highly suspect that the BGE is culling faces past the sides of the view frustum too.

On the other hand a lot of small objects add to the render time too. so you need to find a balance between mesh size and number of objects.

Agreed. A balance must be struck.

I figure a fair rule of thumb is that, poly count being equal, no one object should be outside… say… 80-120% the view frustum volume. Any smaller and you begin to needlessly increase the object count inside the frustum, and any larger and you risk having many polygons for an object out of the frustum. Of course, a pragmatic approach would need to account for polygon density somewhere in there too.

. . .

In any case, I’m guessing that there are maybe two culling phases going on in the BGE. The first is the less expensive bounding box phase. This phase would quickly cut down on huge swaths of polygons via the association with the parent mesh. The second phase is some sort of expensive polygon based culling, probably involving some kind of mesh traversal, polygon sort, or whathaveyou. This second phase would (in theory) benefit the fragment shading step by not filling fragments that aren’t even going to be displayed.

But this is just my baseless speculation. The mesh representation and the amount of texturing/shading no doubt affect the practicality of the second step. Also, it might amount to saving the GPU by burning the CPU, which would be selling the car for gas money.

If you notice at far / near distances object faces disappear, check that it is not camera clipping (near and far planes of camera)

As Agoose77 wrote the near and far is plane is part of the frustum description. That you see pixels disappear is part of the z-Buffer processing not part of the culling.

Background:

  • Frustum Culling removes all objects that will never be visible (as they are completely outside the frustum volume. It performs a few fast calculations per object.
  • Camera clipping is no special processing, it is a result of the z-Buffer processing per pixel. The Z-Buffer is used for fast overlapping calculation. Pixels will fall out of the render if they are not between near and far plane - mathematically because they left the available data range, artistically - because they are not inside the frustum.

Yes, I was in fact seeing camera near/far clipping.

It looked like clipping of whole polygons, but it might be that it is on a per-pixel level. Hard to tell when everything is various shades of gray.

Either way, I have done tests that more or less show there is some kind of culling off the sides of the frustum, in addition to the near and far clipping. Here’s the test if you wish to follow along…

  1. Make a large plane with 2M polygons, give or take.
  2. Randomize the vertexes a bit so you can see these polygons. Also so there is no chance they get “optimized” out.
    3*) Add some texturing/GLSL shader material to make the GPU load more realistic. (* Also do the test without this)
  3. Set the camera close to and squarely facing the surface.
  4. Set the far clipping plane to infinity.
  5. Add some keyboard camera movement, so you can pan and zoom the camera.
  6. Run the simulation, zoom in and out, and watch the framerate and/or GPU utilization.

Zooming away from the object will put increasingly more polygons inside the view frustum. If these polygons are being processed by the GPU the entire time, then there should be no change in performance/GPU utilization.

My Results.
Without texturing, there was indeed no change in performance, regardless of the number of polygons that fall within the view frustum. With texturing, there was a direct correlation in CPU utilization and the number of polygons in the view frustum. So it seems at least that the polygons of a large object are indeed processed by the GPU whether they are visible. There still must be some kind of view frustum clipping, culling, or ignoring happening on a fragment/pixel/texture level though. I suspect it is something like a simple 2D boundary limit/test.

So, if poly-count is slowing you down, and you have any high-poly objects that can’t fit fully inside the view frustum, indications are to break that object into smaller sub-objects, to optimize via object culling.

Further testing would probably be to break the above object into smaller pieces, in accordance with the previously defined method, and see just how much it affects the profiler/GPU utilization under different situations. Any failures to give a performance improvement would still show that there may be no need for object level culling. At least as far as graphics is concerned. But that’s probably a given.

… a failure to improve performance for all situations would be really bad. But given what I am seeing now, I’m confident that won’t be the case.

Anyway, thanks for the input. I will either mark as [Solved], or report back with my next findings. Maybe both.

Infinite far clipping plane is very bad, in terms of render efficiency and z-Buffer precision (detecting overlapping pixels). It should be avoided. (I’m not sure if that is even possible.)

Yes, the number of faces that are rendered have direct influence on the render time. That is normal, but it happens after frustum culling and excludes anything that is culled already.

Frustum culling on face is done too, but it belongs to face rendering (rather than object rendering).

The thumb role is:

  • as many objects as possible outside of the camera frustum (that they are culled away)
  • as less as possible faces at the screen area (to reduce the number of faces to be rendered) [regardless if hidden behind other faces]