View Frustum Culling
In order to visualize a scene from different angles a virtual camera is often used. The virtual camera setup, commonly done with
gluLookAt functions, determines what is visible on screen.
The view frustum is the volume that contains everything that is potentially (there may be occlusions) visible on the screen. This volume is defined according to the camera’s settings, and when using a perspective projection takes the shape of a truncated pyramid.
The apex of the pyramid is the camera position and the base of the pyramid is the far plane. The pyramid is truncated at the near plane, hence the name frustum.
All the stuff that will potentially be visible on screen is inside, at least partially, the truncated pyramid, so there is no need to try and render what is outside the frustum, since it won’t be visible anyway.
In the figure above all the green stuff (totally inside the view frustum) and all the yellow stuff (partially inside) would be rendered, whereas the red stuff will not be rendered. Note that the green sphere is not visible (it is occluded by the yellow ellipse), but it will be rendered anyway because it is inside the view frustum.
The goal of view frustum culling is therefore to be able to identify what is inside the frustum (totally or partially), and cull everything that is not inside. Only the stuff that is inside the frustum, even if only partially, is sent to the graphics hardware. In the end, all that is asked of the graphics hardware is to render what is potentially visible, saving on the processing of all those vertices that are not visible anyway. Furthermore, this can potentially improve the performance of the application since only the vertices that are part of the visible part of the 3D world are kept on the graphics card memory, and these are more likely to fit than the whole 3D world.
This test makes sense if the part of the 3D world that is inside the frustum is significantly smaller than the world itself. But what does significantly smaller mean? That depends on the application. In the extreme case when the whole 3D world is always visible, view frustum culling is just a waste of time because there is nothing to cull. But since this culling technique is so easy to implement and the performance benefits can be very significant it is worth a try.
- Extracting the Planes
- Testing Points and Spheres
- Testing Boxes
- Testing Boxes II
- Source Code
Clip Space Approach
Notes and Refs
Nice post .
However, I have a question about the testing between box and the frustum.
If the box is including or enclosing or even intersect with the frustum , the test may fail, cause all the 8 points are all outside the frustum.
The test is not to check if all points are outside the frustum, but rather to check if they are all on the “wrong” side of a plane.
I have a problem with your View Frustum Culling implementation.
When I have this values:
frustum.setCamInternals(70, 1.83558, 1, 2000);
frustum.setCamDef(Vec3(1032, 2048, 1032), Vec3(1031.31, 2048.4, 1032.61), Vec3(0, 1, 0));
This call returns me FrustumG::INTERSECT :
frustum.boxInFrustum(AABox(Vec3(0, 0, 536870912), 536870912, 536870912, 536870912));
While this is impossible, and this is just an example. I am not good in math and I need you for resolved this problem.
Can you help me?
Hi, it seems that your view vector is pointing mainly in the negative X direction. Given the size of the viewport and its aperture I have some doubts as to an intersection being impossible. Am I missing something here?
The intersection is impossible, I’m sure of that. But the view frustum culling detects a collision. How can I resolve this problem?
Draw the box and the frustum as geometry. Then you’ll be able to see what is going on. Also try using a debugger to locate a potential bug on the implementation. Check the corners of the frustum to see if they are where you expect them to be. In order to have an intersection at least one corner must be outside of the box, and at least one must be inside.
I’ve got a question about the “SetCamDef” funktion – it requires the “position “p” of the camera” and the Point, where the camera is looking at ( “l”) – but in my engine, any object has a position in eye space and a rotation vector in Rad (these two + scale vector gives the modelmatrix of each object). How do i get the “l” vector from this two vectors? Multiply position by rotation? Also, you don’t call the function “setFrustum” in your code “FrustumR” – is the function not required? Because i have a projection matrix and ask me, if i have to give this matrix to this function…
Anyways, thanks for your good work, you’re tutorials are awesome =D
Soon… i hope 🙂
Excellent tutorial, we’ll see how it integrates with my engine, but right now its looking great!
Superb work, works with my code without a single hitch