Notes and homework on scan converting triangles

As I mentioned in class on Wednesday, in order to render cool shaded versions of our animated shapes, we are going to need to paint each triangle into the image, while interpolating color and perspective z.

I know that some of your polygons have four vertices. Fortunately you can always convert a four sided polygon to two triangles at the moment when you need to render it:

```(a,b,c,d) → (a,b,c) and (a,c,d)
```
The most computationally efficient way to do shading is to only apply a shading algorithm (such as the Phong algorithm that Professor Zorin discussed) at the vertices. This is call vertex shading.

The more flexible and powerful (although slower) way to do shading is to apply a shading algorithm at each pixel. This is called pixel shading.

In practice, renderers tend to use a combination of vertex shaders and pixel shaders. For the next week or so we'll just be doing vertex shading, because it is simple and it runs fast. Later we will add pixel shading so you can do things like texturing.

When you do vertex shading, you first do the shading algorithm at each vertex of your polygon - so you already have colors at each vertex, and now you just need to interpolate them. This means that by the time you do scan conversion, the data you have at each vertex is:

```  [ px , py , pz , red , green , blue ]
```
You are going to use the `px` and `py` to figure out which pixel the vertex falls on in the image - That is just the viewport computation.

You are going to interpolate the three vertex `[ red , green , blue , pz]` values over all the image pixels covered by the triangle in order to figure out which triangle is the frontmost one at each pixel of the image, and what color that triangle should be at that pixel. The algorithm to do this is known as the Z-buffer algorithm.

Next week we are going to do the complete Z-buffer algorithm, and tie it together with your wonderful 3D shape modeling/animating software. This week I just want you to work on the core part of the scan conversion: Interpolating vertex values across image pixels.

As we discussed in class, this scan-conversion step is the key place in your rendering pipeline where things are either going to be fast enough to do interactive graphics, or not. There are two things that are necessary in order to make this algorithm go fast:

• You need to use iterative methods. That's just a fancy way of saying that wherever possible, use addition instead of multiplication.

• Use integer arithmetic rather than floating point arithmetic. This is especially important in a language like Java, which implements integer math a lot faster than floating point math.
Also as we discussed in class, the key to making triangle scan-conversion easy to implement and bug-free is to recast it as a simpler problem. In the two diagrams below you see the basic principle of converting a polygon into trapezoids:

Once you have a trapezoid, then, as we said in class, the only thing you need to do is efficiently interpolate the [r,g,b,pz] values from the four corners down to the pixel level.

To find the interpolated values at any given pixel (x,y), you first find the interpolated values at the left and right edges of the scan line, and then you interpolate those two values to get the value at the pixel. In other words:

```          // COMPUTE TOP-TO-BOTTOM INTERPOLATION FRACTION FOR THIS SCAN LINE

ty = (y - TLy) / (BLy - TLy)

// LINEARLY INTERPOLATE TO GET VALUES AT LEFT AND RIGHT EDGES OF THIS SCAN LINE

L = lerp(ty, TL, BL)
R = lerp(ty, TR, BR)

// COMPUTE LEFT-TO-RIGHT INTERPOLATION FRACTION OF THE PIXEL

tx = (x - Lx) / (Rx - Lx)

// LINEARLY INTERPOLATE TO GET VALUE AT PIXEL

[r,g,b,pz]x,y = lerp(tx, L, R)
```
where `L` and `R` are vectors containing values for r,g,b and pz.

Homework due Wednesday March 12

For your homework, which is due next Wednesday, March 12, you should at least demonstrate that you can split a triangle into two trapezoids, and then apply the above math to interpolate [r,g,b,pz] values down to the pixel level. To do this, I suggest you write a Java applet that extends MISApplet, and show that it correctly interpolages given any choices of locations [x,y] and colors [r,g,b] at each of the three triangle vertices.

Once you get that much working, try implementing the speed-ups we discussed in class. As I said above, in order to make this scan-conversion really fast, you can do two things:

• Use iterative methods. To do this, you first compute an amount to increment per scan line when marching down the left edge and the right edge, respectively:
```    // COMPUTE TOTAL NUMBER OF SCAN LINES IN TRAPEZOID

int n = BLy - TLy

dL_dy = (BL - TL) / n
dR_dy = (BR - TL) / n

L = TL
R = TR

for (int y = TLy ; y < BLy ; y++) {

// INCREMENTALLY UPDATE VALUES ALONG LEFT AND RIGHT EDGES

L += dL_dy
R += dR_dy

// COMPUTE TOTAL NUMBER OF PIXELS ACROSS THIS SCAN LINE

int m = Rx - Lx

d_dx = (R - L) / m

[r,g,b,pz] = L

for (int x = Lx ; x < Rx ; x++) {

// INCREMENTALLY UPDATE VALUE AT PIXEL

[r,g,b,pz] += d_dx
}
}
```

• Use integer arithmetic. To do this, you can scale all your values up by some power of two, say 212 = 4096, and do all operations using integers. Then scale everything back down again when you've finally interpolated down to the pixel level.

If you implement both of the above speed-ups, you'll see a very dramatic improvement in running time.