Visible Surface Detection
Soon Tee Teoh
• We want to only draw the visible surfaces.
• Motivation 1: Correctness. If Surface A is
in front of Surface B, then Surface B
should not be seen. If it is rendered, then it
produces a wrong picture.
• Motivation 2: Speed. Trying to render an
invisible surface and later eliminating it is a
waste of time.
• If we want to render front faces only, we can eliminate all
the back-facing polygons.
• How to detect back-facing triangles?
– To determine if a triangle is back-facing, take the dot product
between its normal N, and the view vector V.
• V = P – E, where P is the position of a vertex on the triangle, and E
is the position of the eye/camera.
– If V.N > 0, then it is a back-facing triangle, and should not be
rendered. Otherwise, it is a front-facing triangle and should be
Eye position E V Triangle
Triangle normal N
OpenGL Back-Face Culling
• Enable back-face removal with glEnable(GL_CULL_FACE);
• Disable back-face removal with glDisable(GL_CULL_FACE);
• Then, select which polygons to remove with one of the following
• The default is GL_BACK, so that the back-facing polygons are
• However, remember that in a polyhedron, the convention is to
specify the triangles such that the outward face is the front face.
Therefore, if the camera happens to be inside the polyhedron, we
would use glCullFace(GL_FRONT) to get rid of the front-facing
polygons, so that we see the back-facing ones only.
Depth Buffer Method
• The Depth Buffer Method (also called the
z-buffer method) is used to handle
occlusion, so that only the surface that is
closest to the camera position is shown.
• Using this approach, two frame buffers
need to exist. One is the color buffer,
which keeps the color for each pixel. The
other is the depth buffer, which keeps the
depth of each pixel.
Depth Buffer Method (continued)
• When scan-converting a triangle, use surface rendering method to
calculate the color at each pixel.
• Also, calculate the normalized depth of the pixel. The normalized
depth of each vertex of each triangle is automatically generated by
the viewport normalization matrix. Use the incremental method
(explained in the following slide) to calculate each pixel depth from
the vertex depths.
• Next, compare the new pixel depth with the depth stored for this
pixel in the depth buffer.
• If the new pixel depth is smaller than the stored depth, it means that
the new pixel is nearer to the viewer. Therefore, the new color
replaces the stored color for this pixel in the color buffer, and the
new depth replaces the old depth for this pixel in the depth buffer.
• Otherwise (if the new pixel depth is greater than the stored depth),
the new pixel is ignored. Color and depth buffers for this pixel are
Depth Buffer Method (continued)
The incremental method for calculated depth of a pixel
• Given: The depths of each vertex of a triangle.
• Objective: Get the depth of each pixel rendered for the triangle.
• Suppose that we’re using the scan-line approach.
• Suppose that we have calculated the depth z of the first pixel (x,y)
• Suppose the plane equation of the triangle is Ax + By + Cz + D = 0
• Then, z = (– Ax – By – D)/C
• Now, we want to find the depth z’ of the next pixel (x+1,y) on the
• Now, z’ = (– A(x+1) – By – D)/C
• Simplifying, z’ = z – A/C.
• Now, A/C is a constant for each surface, so we just need one simple
subtraction to get the depth of each successive pixel along the scan-
Disadvantages of the Depth Buffer Method
• Need a lot of memory for the depth buffer.
– Suppose we need 16 bits depth for each pixel, and
there are 1024 x 1024 pixels, then we would need 2
MB of space for the depth buffer.
• Can possibly waste a lot of time calculating the
color of each pixel of a triangle, and then later
get completely obscured by another triangle.
• Precision is less for the depths of triangles
further away from the camera position. (The
depth calculated by the viewport transformation
is only the pseudo-depth.)
Using Depth Buffer in OpenGL
// tell glut to give you a depth buffer
// need to reset the depth buffer before drawing each frame
// need to enable depth testing
// set the depth function. GL_LESS means that the incoming pixel
// passes the depth test if its z-value is less than the currently stored
// value. GL_LESS is the default anyway (so, the following line need
// not be called).
BSP Tree Method
• A BSP (Binary Space-Partitioning) tree is formed by first
choosing a triangle from the set of all triangles in the
• The plane that contains this triangle is called P. Classify
all other triangles into two groups: One group in front of
P, and the other group behind P. All triangles that are
intersected by P are split into multiple smaller triangles,
each of which is either in front of P or behind P.
• Within each group, recursively pick another triangle and
partition all the triangles in this group into two sub-
• Do this until there is only one triangle in each group.
• The result is a tree.
BSP Tree Example
Using BSP Tree for Hidden Surface Removal
• Goal: Render the triangles from back to front
– Go down a BSP tree. At each node, check whether the view point is in
front of the node plane or behind.*
– Descend the far side subtree first and output triangles.
– Then, render the triangle at the node.
– Then, descend the near side subtree and output triangles.
• Advantage compared to depth buffer:
– No need to keep depth buffer (save memory), always overwrite color
– Triangles are rendered back to front, so can do transparency
• Disadvantage remains:
– May possibly waste a lot of time rendering triangles which will eventually
*How to check if a point is in front of the plane: Substitute the coordinates of the point into the plane
expression Ax+By+Cz+D. If the result is greater than zero, the point is in front of the plane.
Is this a valid BSP tree? Is this a valid BSP tree? Is this a valid BSP tree?
G G J
C H C H C H
F F F
D B J D B J A E I
E A A E B D G