CS40: Computer Graphics, Lab 2

Graphics Primitives

By Jeff Kaufman

In this lab I implemented a graphics library for drawing points, lines, circles, and ellipses to provided specifications. The lines, circles, and ellipses are all drawn with versions of Bresenham's Algorithm.

This project was generally more frustrating then the previous one, being much more finicky. I had to fix little bugs in which order to include headers, the declaratons of inline functions, the conversion of Bresenham's Algorithm to work in octants other than the first one, and several other places. None of these were particularly challenging conceptually, but I repeatedly got stuck on them and they gave the whole project a feel of being unbearably fragile.

I implemented Bresenham's algoithm for lines and similar ones for circles and elipses. This worked alright, but they looked awfully jagged. I decided to fix this by implementing antialiasing based on the error term, something that I thought wouldn't be that hard. I implemented this first for lines, and it ended up taking long enough to get that working that I did not implement it for circles or ellipses.

The other reason for not expanding the implementation of antialiasing is that it didn't look that good. The logic was based on the assumption that two pairs of pixels which summed to the same color value would appear to be of the same intensity to the average viewer. Unfortunately, this is not true. People see a full-on pixel, even next to a full-off pixel, as brighter than a pair of half-on pixels. This made the lines look to be varying in color. Even worse, this varied by monitor, with some monitors making them look about the same and others presenting the half-on pair as very dark. If not for this perhaps the implementation of a non-linear coloring algorithm would fix the problem, but with these monitor issues I'm not sure what to say but that this is about as good as antialiasing can look, at least on some monitors.

I also modified the line drawing code to plot two points at each iteration. As tested through the "testbench.c" program, this didn't help very much. On an intel CS lab machine running at 3.0 GHz, it averaged 310,000 lines per second with one point at a time and 315,000 per second with two at a time. I considered this to be a small enough gain that when I redid my line algorithm to add antialiasing I removed the double plotting to simplify the logic.

Making lines and other objects come out in exactly the right places was tricky, and I don't think I have it quite right. The initial value of the error term needs to be set properly, and in some cases my lines look like I might have gotten that wrong. They tend to be close, but I need to do more testing to get the right.

API Info

The basic API is presented in the graphics specification for the lab. I wrote in C, and so implemented the C portion of the spec. There were some cases, notably Point and Color where I could either typedef to an array or a struct, and I chose the struct route. I also implemented two extra functions, which are below.

When I was implementing antialiasing for my lines, I found that I wanted a way to rapidly blend lines into an image, without having to read the value, calculate the replacement value, and set. I wrote two functions, then Image_set_mix and Image_set_mix_int that expand the Image_set of the basic API by taking blending values. In the first version, in addition to the arguments required by Image_set there is a float value that indicates how much to mix in the new color. So we have:
This, while simple, requires slow floating point math. An integerized version would be much better. For Image_set_mix_int I implemented one by having the user pass in a numerator and a denomenator instead of a float:

Pretty Pictures

The test image:

A silly test image of my own is below. The radial lines are very useful for debugging, as you can easily see how the code is handling all eight cases. The shaded lines do a decent job of showing the antialiasing.
A pretty scene:
A 3D trolley car:
A bouncing ball. This ball is sort of silly; it squishes when it bounces, but because I don't really know physics I couldn't get it to squish properly. The squish should take velocity into account but does not. It does, however, demonstrate both my circle and ellipse code.

Jeff Kaufman : 2005
cbr at sccs dot swarthmore dot spam edu. Remove spam.

main page