SCAN CONVERTING A TRIANGLE

There are various tricks you can do to quickly scan-convert a triangle - that is, to convert a triangle into pixels on your framebuffer - but for next Wednesday, March 25, we'll just do it the slow and easy way.

Given a triangle, let's say you've already done all 3D Matrix transformations, the perspective transformation, and the ViewPort Transform on its three vertices A, B and C. So now you have pixel coordinates (Ai, Aj), (Bi, Bj) and (Ci, Cj), where Ai, Bi and Ci refer to pixel column between 0 and W-1 (ie: from the left to the right of the framebuffer), and Aj, Bj and Cj refer to pixel row between 0 and H-1 (ie: from the top to the bottom of the framebuffer).

The most basic step of scan-conversion is to identify which pixels in the framebuffer are inside the triangle. To test whether your algorithm works, you'll want to see whether you can produce a white-against-black image, where the pixels that are in the scan-converted triangle are displayed as white, and all other pixels are displayed as black.

As you will recall from the lecture, a good way to tackle this problem is to divide it into two simpler sub-problems. Rather than trying to scan-convert the entire triangle in one step, we chop it into two trapezoids - a top trapezoid and a bottom trapezoid.

In order to do this, we need to order the three vertices from top to bottom. Let's sort our three vertices A,B, and C by vertical position, from top to bottom, so that after sorting Aj <= Bj <= Cj.

Once we've done this, we need to slice the triangle in half at Bj, so that we can deal with the two halves separately. This slice will produce a new vertex D along the edge between A and C, which has the same vertical position as B, but a different horizontal position (shown in red on the left side of the figure).

We need to find the coordinates of D. Of course we already know Dj, since Dj = Bj. Since D is on the line from A to C, we will need to do a linear interpolation to compute Di.

First, compute the fractional vertical distance of D between A and C. This will be the same as the fractional vertical distance of B between A and C:

t = (Bj - Aj) / (Cj - Aj)
Now do a linear interpolation from Ai to Ci, in order to get the horizontal coordinate Di:
Di = lerp(t, Ai, Ci)
Now we have everything we need to form the two trapezoids (show on the right in the diagram above). The top trapezoid has a degenerate top edge - it consists only of the point A, and a bottom edge that goes between D and B. The bottom trapezoid has a top edge that goes between D and B, a degenerate top edge - it consists only of the point C.

To scan-convert either of these trapezoids, we can ignore the fact that the trapezoid has a degenerate top edge or bottom edge, and just treat it as a general trapezoid with a horizontal top edge between a top-left vertex TL and a top-right vertex TR, and a horizontal bottom edge between a bottom-left vertex BL and a bottom-right vertex BR:

The trick will be to march along scan-lines from the top edge down to the bottom edge. At each scan-line we will define a left vertex L and a right vertex R (shown in red in the figure). Once we have found L and R, we can just fill in all the contiguous pixels between them, and we're done.

How do we find L and R for any given scan-line? As usual, we do this by linear interpolation. First we compute a fraction t for each scan-line, and then we use that t to do a lerp operation. Here is a pseudo-code description of this part of the scan-conversion algorithm:

   for (int j = TLj ; j < BLj ; j++) {   // LOOP THRU SCAN LINES
      t = (j - TLj) / (BLj - TLj);       // COMPUTE FRACTION t
      Li = lerp(t, TLi, BLi);            // COMPUTE LEFT EDGE FOR SCAN LINE
      Ri = lerp(t, TRi, BRi);            // COMPUTE RIGHT EDGE FOR SCAN LINE
      for (int i = Li ; i < Ri ; i++)    // FILL PIXELS IN SCAN LINE
         fillPixel(i,j);
   }
Now you have all of the information you need to make a very simple demonstration of triangle scan-conversion. By next Wednesday, March 25, implement a java applet that demonstrates your implementation of triangle scan-conversion, along the lines described above. Your demo applet can generate the three triangle vertices randomly if you wish, or it can prompt the user to place the three vertices by clicking. Whatever you prefer.