view frustum culling

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
silvia_steven_2000
Posts: 2
Joined: Mon Jul 26, 2004 8:51 am

view frustum culling

Post by silvia_steven_2000 »

Hi all

in scene manager where view frustum culling is handled we have
return !(tbox.intersectsWithBox(cam->getViewFrustrum()->boundingBox));
what will happen to scene nodes that are inside the view frustum bounding box
and outside the view frustum itself. it seems they are not going to be culled
while they must be culled.

thanks for help.
Asterisk Man
Posts: 62
Joined: Wed Jun 09, 2004 5:51 am

Post by Asterisk Man »

It's done this way because it is faster than to check the object's position relative to the 6 planes. You may get more objects drawn, but it still should be faster than the pickier method.
silvia_steven_2000
Posts: 2
Joined: Mon Jul 26, 2004 8:51 am

Post by silvia_steven_2000 »

that is great but I am not saying anything about performance, so u r saying
that there r some objects getting drawn while they are actually outside the
view frustum, is that what u r saying ?
what would be the case if some of these ojects r huge meshes,
would not this slow down rendering ?
Guest

Post by Guest »

W.r.t. slowdown: not really (well, not much, anyway).

The underlying hardware will still cull any triangles that fall outside the frustrum, so it won't matter if the objects are big or small. Although the complexity does matter - if there are a lot of triangles in an object, there will be a lot of triangles to cull.

But at least non-culled objects won't be impacted by fillrate, and the graphics card is bound to be better at culling triangles than the CPU at culling objects.

Of course it's not a very simple comparison - I think it really depends on how complex the objects are. My guess is that the choice of this bounding box approach is based on comparing actual performance.
Guest

Post by Guest »

very strange, if the underlying hardware culls objects that fall outside the
frustum, why do we need to care about frustum culling from the first beginning?
mm765
Posts: 172
Joined: Fri May 28, 2004 10:12 am

Post by mm765 »

because the data has to be transferred to the graphics card first. and transferring less data should is faster (if it is a significant amount) than transferring more data and have the gpu cull the unneded triangles.
take a large terrain for example where nearly 3/4th of the triangles would not need to be sent (assuming a fov of 90 degrees) which would be faster than sending all data and let the gpu do the culling. so you would do the culling beforehand for that.
Guest

Post by Guest »

For a somewhat more complete explanation:

Take a model with 500 triangles.
The view frustrum will be shaped like a trapezium:

(Cross-section)

Code: Select all

---------
\       /
 \     /
  \   /
   ---
Although it will be much narrower at the narrow end than at the wide end.

If the CPU sends all 500 triangles, every time, the processor on the graphics card (the GPU) has to cull those triangles every time.
Triangle culling _is_ efficient on those cards, but 500 times almost nothing is still something.

If the CPU can efficiently cull the whole set of 500 triangles, that is, in less time than the GPU culls the 500 separate triangles, there's a win.
Obviously you don't want the CPU to cull individual triangles. You'll be hard-pressed to outcull the GPU there.

So this is where bounding boxes come in.

Silvia_steven_2000 obviously looks at the trapezium shape of the frustrum, and thinks (and I would in principle agree):
the bounding box is roughly twice as big as the frustrum itself, so the CPU is not culling the object in half of the cases.

Since the GPU will still cull the triangles, this does not result in incorrect output.
Also, since the frame rate is dependent also on a limited fillrate (how quickly the pixels are written to the frame buffer), you don't get the full penalty of rendering 500 triangles, just that of culling 500 triangles.

My instinct says that if you're rendering a lot of complex objects, it's probably better to cull using the actual shape of the frustrum rather than its bounding box, but I have no idea at what complexity or number of objects the extra cost of checking 8 corners of all bounding boxes against 6 planes becomes worthwile.
Then again, you would only need to clip against the six planes if the object intersects the frustrum's bounding box.
It obviously depends on relative CPU/GPU power.

As you can see, it's not very simple to categorically say what's better, so it's best to measure, maybe even use different methods based on the performance of the user's machine.
I figure NiKo did his measurements and decided a simple bounding box/bounding box check was more efficient. But that _is_ an assumption on my part.
T101
Posts: 44
Joined: Thu Jul 29, 2004 4:41 pm

Post by T101 »

That last post was mine by the way. I did not register before, since until about a week ago I didn't post - I just browsed.

For the purists: obviously, the frustrum is more like a capped pyramid, so the bounding box is closer to 4 times the actual frustrum.
Guest

Post by Guest »

when u said that the bounding box is as twice in size as the frustum,
u really put your hand exactly on the question I asked. it would be
nice if niko comments on that.
hub
Posts: 10
Joined: Thu Sep 02, 2004 5:39 pm

Post by hub »

It was said that the hardware is resoinasible for the polygon culling. If so, what does the IrrichtDevice::getPrimitiveCountDrawn() refer to? Does it really show how many primitives were actually drawn (and then optionally clipped by some Z-buffer operations) or just primitives which were sent to the graphic card but might not have been rendered (due to the culling mentioned?)
Performance drops in complex scenes suggest that the first option is correct... Has anyone any idea what the situation really looks like?
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

Ibelieve irrlicht counts all primitivesit sneds to the gpu. As far as I know thwe gpu gives no feedback on what is actually rendered.

As for frustum verses aabb culling: I believe in the function CSceneManager::isNodeCulled (or something like that) niko uses aabb culling but has the frustum culling code underneath it, just commented. Switch things so the aabb code is commented out and test to see which gives faster performance
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.

Crucible of Stars
x4861
Posts: 24
Joined: Fri Feb 18, 2005 10:19 am

Post by x4861 »

I just had this problem as well. The commented code doesn't cull against frustrum, but transformed bounding box. I played around with frustrum culling and found a simple algorithm that can be used. The idea is to cull objects based on their bounding sphere.

If object bounding sphere doesn't intersect with view frustrum and is outside, then don't draw it. Here is implementation:

Code: Select all

bool CSceneManager::isCulled(ISceneNode* node)
{
	ICameraSceneNode* cam = getActiveCamera();
	if (!cam)
		return false;

	core::aabbox3d<f32> box = node->getBoundingBox();
	node->getAbsoluteTransformation().transformBox(box);
	SViewFrustrum* ViewArea = cam->getViewFrustrum();
	vector3df sphere_pos;
	sphere_pos = box.getCenter();
	float sphere_r = (float)sphere_pos.getDistanceFrom(box.MinEdge);
	float d=0;
	for(u16 i=0;i<6;i++)
	{
		d = ViewArea->planes[i].Normal.dotProduct(sphere_pos)+ViewArea->planes[i].D;
		if(d >= sphere_r)
			return true;
	}
	return false;
}
To get more detailed explanation, go to:
http://www.gamasutra.com/features/20020717/bacik_04.htm

Anyway, this culling speeds up only for larger scenes where you have many objects.
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

As for frustum verses aabb culling: I believe in the function CSceneManager::isNodeCulled (or something like that) niko uses aabb culling but has the frustum culling code underneath it, just commented. Switch things so the aabb code is commented out and test to see which gives faster performance
oops, i was forgetting what that commented code is. It isn't real frustum culling. I'm not sure what it is



If object bounding sphere doesn't intersect with view frustrum and is outside, then don't draw it. Here is implementation
What sort of speed difference do you get with this? Have you done any tests?

I wrote my own frustum culling function a little while ago, though I haven't put it in the ScenManager, I was just using it in my portal rendering system to avoid performing computations on portals that weren't visible anyway

Code: Select all

   bool CPortalSystem::isNodeFrustumCulled(ISceneNode* node)
   {
     	if (!node->getAutomaticCulling())
	      {return false;}
	      
      const SViewFrustrum* frust=mgr->getActiveCamera()->getViewFrustrum();
      core::aabbox3d<f32> tbox=node->getTransformedBoundingBox();
      for(int i=0;i<scene::SViewFrustrum::VF_PLANE_COUNT;i++)
      {
        if(tbox.classifyPlaneRelation(frust->planes[i])==core::ISREL3D_FRONT)
        {return true;}
      }
      return false;
   }
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.

Crucible of Stars
x4861
Posts: 24
Joined: Fri Feb 18, 2005 10:19 am

Post by x4861 »

Ahh, this is almost the same! Your approach is a liiiiitle bit slower, but the result is a liiitle bit better :) And more elegant too.

Anyway, I did some tests for my game (see Alpha Foundation in Project forum) and I got 1.5-3 times faster with this culling on large areas with many objects. Mainly it depends on position and orientation of camera. And it makes sence, since bounding box of Frustrum is about 4 times bigger than the frustrum itself.
Post Reply