view frustum culling
-
- Posts: 2
- Joined: Mon Jul 26, 2004 8:51 am
view frustum culling
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.
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.
-
- Posts: 62
- Joined: Wed Jun 09, 2004 5:51 am
-
- Posts: 2
- Joined: Mon Jul 26, 2004 8:51 am
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.
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.
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.
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.
For a somewhat more complete explanation:
Take a model with 500 triangles.
The view frustrum will be shaped like a trapezium:
(Cross-section)
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.
Take a model with 500 triangles.
The view frustrum will be shaped like a trapezium:
(Cross-section)
Code: Select all
---------
\ /
\ /
\ /
---
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.
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?
Performance drops in complex scenes suggest that the first option is correct... Has anyone any idea what the situation really looks like?
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
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
Crucible of Stars
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:
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.
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;
}
http://www.gamasutra.com/features/20020717/bacik_04.htm
Anyway, this culling speeds up only for larger scenes where you have many objects.
oops, i was forgetting what that commented code is. It isn't real frustum culling. I'm not sure what it isAs 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
What sort of speed difference do you get with this? Have you done any tests?If object bounding sphere doesn't intersect with view frustrum and is outside, then don't draw it. Here is implementation
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
Crucible of Stars
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.
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.