November 2000

Before geometry is sent to a rendering engine it is often desirable
to determine whether or not it is visible and therefore need not
be rendered. While rendering engines such as OpenGL clip the geometry
themselves, it still requires the overhead of the geometry being sent to
the engine.

In most 3D rendering applications a perspective projection is applied.
The volume of space that is visible is called the view frustum, an example
is shown below. It is defined by four planes (top, bottom, left, right)
and optionally a front and back cutting plane.
The near and far cutting planes are normally specified as scalars, distances
along the view direction vector. The sides and top/bottom can be specified
directly or they are computed from the camera aperture. In some packages
this is calculated from the
vertical aperture, some on the horizontal,
whichever is chosen the other is fixed given the ratio of the window
width and height.

In order to determine whether part of a primitive is inside the frustum it
is necessary to check that every vertex in the primitive is outside
the volume. To determine this, compute the vertices of each plane
making up the frustum. Each plane can be written in the form,
Ax + By + Cz + D = 0. The constants A,B,C,D can be calculated from any
three points on the planes (since all four points are coplanar) say
(x_{1},y_{1},z_{1}),
(x_{2},y_{2},z_{2}), and
(x_{3},y_{3},z_{3}) as follows:

B = z

C = x

- D = x

In order to test whether a point (x,y,z) is on the left or right of the plane compute Ax + By + Cz + D. If the result is greater than zero then the point is on the same side as the normal (A,B,C), if less than zero then it's on the opposite side, if zero then it lies on the plane.

A parallel (orthographic) projection still consists of a viewing volume but it is a much simpler shape, a box. Clipping against such a volume uses the same techniques discussed here.

In many applications there would be significant overhead in testing every single point of low level primitives. The alternative is to group primitives together into higher level shapes, then one simply tests the vertices of the bounding box of the shape to determine whether it is inside or outside the frustum. When the shape intersects the view frustum one can choose whether to further test the individual primitives or simple pass the whole shape to the rendering engine.