Microsoft DirectX 9.0

Cull Sample


This sample illustrates how to cull objects whose object bounding box (OBB) does not intersect the viewing frustum. By not passing these objects to Microsoft?Direct3D? you save the time that would be spent by Direct3D transforming and lighting these objects, which will never be visible. The time saved could be significant if there are many such objects or if the objects contain many vertices.

More elaborate and efficient culling can be done by creating hierarchies of objects, with bounding boxes around groups of objects, so that not every object's OBB has to be compared to the view frustum.

It is more efficient to do this OBB/frustum intersection calculation in your own code than to use Direct3D to transform the OBB and check the resulting clip flags.

You can adapt the culling routines in this sample meet the needs of programs that you write.


Source: (SDK root)\Samples\C++\Direct3D\Cull

Executable: (SDK root)\Samples\C++\Direct3D\Bin

User's Guide

When you run this program, you'll see a scene with teapots rendered into two viewports. The right viewport uses the view frustum that the code will cull against. The left viewport has an independent camera, and shows the right viewport's frustum as a visible object, so you can see where culling should occur. Fifty teapots are randomly placed in the scene and they are rendered along with their semitransparent OBBs.

The teapots are colored as follows to indicate their cull status.

ColorDescriptionCull status
Dark greenThe object was quickly determined to be inside the frustum.CS_INSIDE
Light greenThe object was determined after some work to be inside the frustum.CS_INSIDE_SLOW
Dark redThe object was quickly determined to be outside the frustum.CS_OUTSIDE
Light redThe object was determined after some work to be outside the frustumCS_OUTSIDE_SLOW

You should see only green teapots in the right window. Note that most teapots are either dark green or dark red, indicating that the slower tests are not needed for the majority of cases.

To move the camera for the right viewport, click the right side of the window, then use the camera keys listed below to move around.

To move the camera for the left viewport, click on the left side of the window, then use the camera keys listed below to move around.

You can also rotate the teapots to set up particular relationships against the view frustum. You cannot move the teapots, but you can get the same effect by moving the frustum instead.

The following table lists the keys that are implemented. You can use menu commands for the same controls.

F1Shows help or available commands
F2Prompts the user to select a new rendering device or display mode
ALT+ENTERToggles between full-screen and windowed modes
ESCExits the application
W, S, ARROW KEYSMoves the camera
Q, E, A, ZRotates the camera
Y, U, H, JRotates the teapots
NMoves the left camera to match the right camera
MMoves the right camera to its original position

Programming Notes

The OBB/viewport intersection algorithm used by this program is:

  1. If any OBB corner point is inside the frustum, return CS_INSIDE.
  2. Else if all OBB corner points are outside a single frustum plane, return CS_OUTSIDE.
  3. Else if any frustum edge penetrates a face of the OBB, return CS_INSIDE_SLOW.
  4. Else if any OBB edge penetrates a face of the frustum, return CS_INSIDE_SLOW.
  5. Else if any point in the frustum is outside any plane of the OBB, return CS_OUTSIDE_SLOW.
  6. Else return CS_INSIDE_SLOW.

The distinction between CS_INSIDE and CS_INSIDE_SLOW, and between CS_OUTSIDE and CS_OUTSIDE_SLOW, is provided here only for educational purposes. In a shipping application, you probably would combine the cull states into just CS_INSIDE and CS_OUTSIDE, because usually you need to know only whether the OBB is inside or outside the frustum.

The culling code shown here is written in a straightforward way for readability. It is not optimized for performance. Additional optimizations can be made, especially if the bounding box is a regular box (for example, the front and back faces are parallel). This algorithm could be generalized to work for arbitrary convex bounding hulls to allow tighter fitting against the underlying models.

This sample uses common Microsoft DirectX?code that consists of programming elements such as helper functions. This code is shared with other samples in the DirectX software development kit (SDK). You can find the sample framework headers and source code in (SDK root)\DXSDK\Samples\C++\Common\Include and (SDK root)\DXSDK\Samples\C++\Common\Src.

© 2002 Microsoft Corporation. All rights reserved.