1) Swiss Cheese
The first task is to take the polygon with transparent stripes and modify it so that the polygon has a number of circular holes. You will do this by modifying the alpha value on a per-fragment basis. In particular, you should create an array of holes on the polygon that are arranged in a grid of 3 by 3. Make sure that this polygon is the last one drawn, so the transparency will be handled correctly from all viewing directions.
2) Mandelbrot Set
The third task is to draw the fractal known as the Mandelbrot Set. You will take one of the squares from the example code and modify it so that you display a white Mandelbrot set on some colored background. The colors (and possibly color bands) for the background are for you to decide. Let z(n+1) = z(n)^2 + c, where z and c are both complex numbers. The Mandelbrot set is essentially a map of what happens when using different values of c (which correspond to different locations in the plane). Let z(0) = (0,0), and look at the values z(1)=z(0)^2+c, z(2)=z(1)^2+c, and so on. Plugging the result of a function back into itself is called iteration. If these iterated values stay near zero (never leave a circle of radius 2), then draw a white dot at the location c. If the values do leave the circle, color them something else. Do this for all the values for values of c such that cx is in [-2,1.5] and cy is in [-1.2,1.2]. The result is the Mandelbrot Set. Use 20 iterations of the function to create your Mandelbrot set.
3) Edge Detection
The second task is to perform what is called "edge detection" in the image processing literature. You will write a Cg fragment program to perform several texture lookups in order to find edges in images. We will provide the input images as a texture (a picture of a duck). Since we wish to do this for a gray-scale image, and because the input image is in color, you will first have to convert color pixels to gray-scale values. Then you will use what is known as a Laplacian filter to estimate the "edge-ness" of a pixel. The Laplacian filter simply takes the values of the four surrounding pixels, sums them, and subtracts four times the value of the middle pixel. You will have to map the resulting value to the range of gray-scale values that can be displayed.
4) Wavy
The fourth and final task is to write a vertex program to modify the geometry of a collection of polygons. Your task is to replace one of the squares with a wiggly square -- similar to a wavy tin roof. You will need to replace the original square with many tiny squares. Then your vertex program will displace these vertices using a sine or cosine wave. You will also have to calculate reasonable surface normals for these new vertex positions.
Sample results

You should tackle this assignment by modifying the fragment and vertex code to carry out the tasks listed above. One by one, you should modify the simple polygons that we provide into much more beautiful polygons that show off the power of Cg programming. The key to success in programming Cg is to make small changes to working code, and verify that each of your changes does what you expect. Do not expect to write an entire Cg program from scratch, replace the example code, and have it work beautifully the first time. Debugging Cg code is an art. You can't single-step through Cg code, you can't set breakpoints, and you can't print out intermediate values. Your only form of output from Cg programs is the resulting image you see on the screen. To debug, you must make clever use of the framebuffer to display intermediate values as pixel colors. Don't forget that pixel colors must be in the range of zero to one.
The example code is in several parts. The OpenGL code for the CPU is called "main.cpp", and it contains all of the C++ code that is needed to execute the vertex and fragment shaders that we provide. OpenGL provides an interface for the Cg program. Vertex information is first passed from the OpenGL program into the vertex Cg program, then the vertex Cg program's output will be used as an input to the fragment Cg program. "common.cg" defines the input and output structures.
There are two examples of a vertex program, and they are called "vertex_prog1.cg" and "vertex_prog2.cg". Currently they are identical. Modify one of these for the wavy task. In the example code, vertex programs convert the vertex from the world space to the eye space, and calculate the reflected diffuse intensity from a single point light source.
There are several fragment programs, and they have names "fragment_progX.cg", where X is an integer from 1 to 5. You will need to modify some of these to create the necessary fragment shaders for the first three tasks. Modify fragment_prog1.cg for the swiss cheese example because it already shows how to modify the alpha channel (transparency). "fragment_prog3.cg" uses the image texture called "image_tex". You can write your edge detection program based on that.
It should be noted that Cg programs are best supported by Nvidia Geforce FX graphics cards. So don't get surprised if the program does not work on your machine. You can use those machines in the digital media lab (behind the states cluster).
Cg toolkit can be downloaded from: http://developer.nvidia.com/object/cg_toolkit.html or: Cg_lib.zip
Some Cg tutorials:
Hello, Cg: http://developer.nvidia.com/object/hello_cg_tutorial.html
Cg in Two pages: http://developer.nvidia.com/attach/7076