Backface culling#

The simplest hidden surface determination method is backface culling which, as the name suggests, we remove all polygons that have a normal vector facing away from the viewer, and therefore considered back facing. In doing this, when we only render the front facing polygons, objects appear solid.

Consider the diagram in Fig. 77 which shows a hexagonal object with face polygons \(A\) to \(F\) which have their normal vectors pointing away from the centre of the object (this is done when we define the object space). When viewed from the viewer position on the left polygons \(A\), \(B\) and \(C\) are front facing and polygons \(D\), \(E\) and \(F\) are back facing.

../_images/backface_culling_1.svg

Fig. 77 All polygons#

Using backface culling if we only render the front facing polygons then from the point of view of the viewer the object is unchanged and appears solution (Fig. 78)

../_images/backface_culling_2.svg

Fig. 78 Front facing polygons only#

To determine whether a polygon is front or back facing we can use the dot product. Consider Fig. 79 that shows a front facing polygon. The angle \(\theta\) between the polygon normal vector and a viewing vector from the viewer to the polygon is greater that \(\pi/2\). Alternatively a similar diagram in Fig. 80 that shows a back facing polygon where the angle between the normal vector and viewing vector is less than \(\pi/2\).

../_images/front_facing_polygon.svg

Fig. 79 Front facing polygon#

../_images/back_facing_polygon.svg

Fig. 80 Back facing polygon#

Recall that the geometric definition of the dot product is

\[ \begin{align*} \mathbf{a} \cdot \mathbf{b} = |\mathbf{a}| |\mathbf{b}| \cos(\theta), \end{align*} \]

and since \(\cos(\pi/2) = 0\) then a polygon is front facing if \(\mathbf{n} \cdot \mathbf{v} < 0\).

Definition 22 (Front facing polygons)

A polygon that has a normal vector \(\mathbf{n}\) is front facing if

\[ \begin{align} \mathbf{n} \cdot \mathbf{v} < 0, \end{align} \]

where \(\mathbf{v}\) is the viewing vector pointing from the viewer to the polygon.

Algorithm 3 (Backface culling)

Inputs A screen space defined by a homogeneous vertex matrix \(V\), a face matrix \(F\) and a viewing position \(\mathbf{p}\)

Outputs A face matrix containing the front facing polygons.

  • \(F_{front} \gets \emptyset\)

  • For each face in \(F\)

    • \(\mathbf{v}_{1,2,3} \gets\) first three vertices in the current face

    • \(\mathbf{n} \gets (\mathbf{v}_2 - \mathbf{v}_1) \times (\mathbf{v}_3 - \mathbf{v}_2)\)

    • If \(\mathbf{n} \cdot (\mathbf{v}_1 - \mathbf{p}) < 0\)

      • Add face to \(F_{front}\)

  • Return \(F_{front}\)

Example 35

A tetrahedron object is defined by the following homogeneous screen space co-ordinates and face matrix

\[\begin{split} \begin{align*} V &= \begin{pmatrix} 1 & 3 & 2 & 2 \\ 2 & 2 & 2 & 4 \\ -6 & -5 & -3 & -5 \\ 1 & 1 & 1 & 1 \end{pmatrix}, & F &= \begin{pmatrix} 1 & 3 & 2 \\ 1 & 2 & 4 \\ 2 & 3 & 4 \\ 1 & 4 & 3 \end{pmatrix} \end{align*} \end{split}\]

The object is viewed looking down the \(z\)-axis from the viewing position at \((0, 0, 1)\). Determine which of the faces of the object are front facing.

Solution

Face 1 :

\[\begin{split} \begin{align*} \mathbf{n} &= (\mathbf{v}_3 - \mathbf{v}_1) \times (\mathbf{v}_2 - \mathbf{v}_3) \\ &= \left( \begin{pmatrix} 2 \\ 2 \\ -3 \end{pmatrix} - \begin{pmatrix} 1 \\ 2 \\ -6 \end{pmatrix} \right) \times \left( \begin{pmatrix} 3 \\ 2 \\ -5 \end{pmatrix} - \begin{pmatrix} 2 \\ 2 \\ -3 \end{pmatrix} \right) \\ &= \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ 1 & 0 & 3 \\ 1 & 0 & -2 \end{vmatrix} = \begin{pmatrix} 0 \\ 5 \\ 0 \end{pmatrix}, \\ \mathbf{n} \cdot (\mathbf{v}_1 - \mathbf{p}) &= \begin{pmatrix} 0 \\ 5 \\ 0 \end{pmatrix} \cdot \begin{pmatrix} 1 \\ 2 \\ -7 \end{pmatrix} = 10 > 0, \end{align*} \end{split}\]

therefore face 1 is back facing.

Face 2:

\[\begin{split} \begin{align*} \mathbf{n} &= (\mathbf{v}_2 - \mathbf{v}_1) \times (\mathbf{v}_4 - \mathbf{v}_2) \\ &= \left( \begin{pmatrix} 3 \\ 2 \\ -5 \end{pmatrix} - \begin{pmatrix} 1 \\ 2 \\ -6 \end{pmatrix} \right) \times \left( \begin{pmatrix} 2 \\ 4 \\ -5 \end{pmatrix} - \begin{pmatrix} 3 \\ 2 \\ -5 \end{pmatrix} \right) \\ &= \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ 2 & 0 & 1 \\ -1 & 2 & 0 \end{vmatrix} = \begin{pmatrix} -2 \\ -1 \\ 4 \end{pmatrix}, \\ \mathbf{n} \cdot (\mathbf{v}_1 - \mathbf{p}) &= \begin{pmatrix} -2 \\ -1 \\ 4 \end{pmatrix} \cdot \begin{pmatrix} 1 \\ 2 \\ -7 \end{pmatrix} = -32 < 0, \end{align*} \end{split}\]

therefore face 2 is front facing.

Face 3:

\[\begin{split} \begin{align*} \mathbf{n} &= (\mathbf{v}_3 - \mathbf{v}_2) \times (\mathbf{v}_4 - \mathbf{v}_3) \\ &= \left( \begin{pmatrix} 2 \\ 2 \\ -3 \end{pmatrix} - \begin{pmatrix} 3 \\ 2 \\ -5 \end{pmatrix} \right) \times \left( \begin{pmatrix} 2 \\ 4 \\ -5 \end{pmatrix} - \begin{pmatrix} 2 \\ 2 \\ -3 \end{pmatrix} \right) \\ &= \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ -1 & 0 & 2 \\ 0 & 2 & -2 \end{vmatrix} = \begin{pmatrix} -4 \\ -2 \\ -2 \end{pmatrix}, \\ \mathbf{n} \cdot (\mathbf{v}_2 - \mathbf{p}) &= \begin{pmatrix} -4 \\ -2 \\ -2 \end{pmatrix} \cdot \begin{pmatrix} 3 \\ 2 \\ -6 \end{pmatrix} = -4 < 0, \end{align*} \end{split}\]

therefore face 3 is front facing.

Face 4:

\[\begin{split} \begin{align*} \mathbf{n} &= (\mathbf{v}_4 - \mathbf{v}_1) \times (\mathbf{v}_3 - \mathbf{v}_4) \\ &= \left( \begin{pmatrix} 2 \\ 4 \\ -5 \end{pmatrix} - \begin{pmatrix} 1 \\ 2 \\ -6 \end{pmatrix} \right) \times \left( \begin{pmatrix} 2 \\ 2 \\ -3 \end{pmatrix} - \begin{pmatrix} 2 \\ 4 \\ -5 \end{pmatrix} \right) \\ &= \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ 1 & 2 & 1 \\ 0 & -2 & 2 \end{vmatrix} = \begin{pmatrix} 6 \\ -2 \\ -2 \end{pmatrix}, \\ \mathbf{n} \cdot (\mathbf{v}_1 - \mathbf{p}) &= \begin{pmatrix} 6 \\ -2 \\ -2 \end{pmatrix} \cdot \begin{pmatrix} 1 \\ 2 \\ -7 \end{pmatrix} = 16 > 0, \end{align*} \end{split}\]

therefore face 4 is back facing.

MATLAB code#

The MATLAB function front_polygons(V, F, p) defined below takes inputs of the vertex and face matrices \(V\) and \(F\) and the viewing position \(\mathbf{p}\) and returns a face matrix containing the front facing polygons.

function Ffront = backface_culling(V, F, p)

Ffront = [];
for i = 1 : size(F, 1)
    v1 = V(1:3,F(i,1))
    v2 = V(1:3,F(i,2));
    v3 = V(1:£,F(i,3));
    n = cross(v2 - v1, v3 - v2);
    if dot(n, v1 - p) < 0
        Ffront = [Ffront ; F(i,:)];
    end
end

end

The affect of applying backface culling to the screen space from Example 32 is shown in Fig. 81.

../_images/backface_culling_example.png

Fig. 81 The screen space from Example 32 plotted using only front facing polygons.#

Unfortunately using backface culling alone is not sufficient to remove hidden surfaces. This means that the church object which should be in the background and partially obscured by the house object in the foreground has been plotted over the top of the house object.