Here is the sequence of calculations to do per frame, commonly called the "rendering pipeline":

Clear both the pix buffer and the zbuffer Loop through geometry objects: Compute M_{N}, the inverse transpose of animation matrix M for this geometry object Loop through all vertices of the geometry object: For each vertex (x,y,z,nx,ny,nz): Use matrix M to transform x,y,z to x',y',z' Use matrix M_{N}to transform nx,ny,nz to nx',ny',nz' Use the Phong algorithm to transform nx',ny',nz' to r,g,b For each face of the geometry object: If face has more than three vertices, split into triangles For each triangle: Clip triangle to the plane z = -ε If clipped shape has four vertices, split into two triangles to render separately. Apply perspective transform to each vertex. Now you have (px,py,pz,r,g,b). Apply viewport transform to each vertex. Now you have (i,j,pz,r,g,b). Split triangle into two trapezoids, in preparation for scan-conversion. For each of the two trapezoids with corners (TL, TR, BL, BR): Each corner is located at pixel (i,j) and contains a value of (r, g, b, pz) where pz is the perspective z coordinate. Loop through each scan scan-line j of the trapezoid between TL_{j}and BL_{j}: interpolant t_{j}= (j - TL_{j}) / (BL_{j}- TL_{j}) left edge point L = lerp(t_{j}, TL, BL) right edge point R = lerp(t_{j}, TR, BR) Loop through pixels i of scan-line, between L_{i}and R_{i}: interpolant t_{i}= (i - L_{i}) / (R_{i}- L_{i}) (r,g,b,pz) = lerp(t_{i}, L, R) If (pz > zbuffer(i,j)) set zbuffer(i,j) to pz set pix(i,j) to r,g,b

* Some helpful notes*:

Here is a link to a class/method for computing the inverse of a 4×4 matrix: Invert.java

As we discussed in class, the algorithm for clipping a triangle against a plane (in this case the plane P = [0,0,-1,&epsilon] is:

Start with an empty output polygon For each vertex A: If A is on the positive side of the polygon (ie: dot(P,A) ≥ 0), then add A to the output polygon. Consider the edge A,B, where B is the next vertex around the polygon. If the sign of dot(P,A) differs from the sign of dot(P,B), then do: t = (0 - dot(P,A)) / (dot(P,B) - dot(P,A)) Add interpolated vertex C = lerp(t, A, b) to the output polygon.

If you have trouble with the clipping, then you can cheat by just rejecting any triangle that has at least one vertex on the positive z side3. It will give you occasional "popping" artifacts, but it's better than nothing.