$29
The purpose of this assignment is to use the GPU (vertex and fragment processors) to carry out various rendering tasks. You will write four short fragment programs that create various patterns and textures. In addition, you will write one vertex program that will change the geometry of a simple surface. Note that unlike previous assignments, this one is not divided into part A and part B.
The code that you create will take the simple examples we provide and modify them to carry out a set of tasks. Here is a list of the four tasks:
Rings
The first task is to take the translucent blue polygon and modify it so that it looks like five intersecting rings. You will achieve this by modifying the alpha value on a per-fragment basis, using a fragment program. In particular, you should begin by making a single opaque disk, based on the distance from the current location to the center of the polygon. Once you have one such disk working, then figure out how you can remove the center of this disk to make it a ring. Finally, put together several such rings. Make sure that this polygon is the last one drawn, so the transparency will be handled correctly from all viewing directions.
Blur
The second task is to perform blurring of an image. You will write a GLSL fragment program to perform a number of texture lookups in order to blur the color in an image. We will provide the input images as a texture (a picture of a duck). At each texture coordinate position, you will calculate the average of a number of texel colors in a square around the current texel. These positions of this square of texels should start 10 texels to the left and extends 10 texels to the right, and also have the same -10 to 10 range in the vertical direction. By summing up the colors of these texels and dividing by the number of texels, you will create an average color in the square. Use this average color as the final fragment color. This should produce a blurred version of the duck.
Bumps
The third task is to write a vertex program to modify the geometry of a collection of polygons. Your task is to replace one of the quads with a “bump creator”. You will need to subdivide the original quad with many tiny quads by modifying the Processing code in p4_gpu.py. Note that you will need to subdivide the quad in both x and y directions. Then your vertex program will displace these vertices along the normal vector using the intensity of the closest texel to the vertex from the provided bump image. Do not move the vertices out of the plane in the p4_gpu.py file -- this must be done in the vertex shader! You should pass a collection of equal area, planar quads into the shader. You should subdivide the quad into at least a 30x30 grid, but no more than a 60x60 grid. Finally, be sure that your final geometry gets its color from the given bump texture. To make the color match the geometry better, modify the color so that the centers of the bumps are white, and the cracks between the are black (as shown in the results below).
Fractal Set
The final task is to draw a kind of fractal called a Julia Set that is related to the Mandelbrot Set. You will take one of the squares from the example code and modify it so that you display a white fractal set on some colored background (red in the example below). The colors (and possibly color bands) for the background are for you to decide. Let z(i+1) = z(i) * z(i) + c, where z and c are both complex numbers, and where * denotes complex multiplication. A Julia set is essentially a map of what happens when using one value for c, but different starting values for z (which correspond to different locations in the plane). For some given value for c, let z(0) = some position in the complex plane, and look at the values z(1) = z(0) * z(0) + c, z(2) = z(1) * z(1) + c, and so on. Plugging the result of a function back into itself is called an iteration. If these iterated values stay near zero (never leave a circle of radius 4), then draw a white pixel at the location for z(0). If the values do leave the circle, color them something else (e.g. red). Do this for all the values for values of z such that z.real is in the range [-1.5, 1.5] and z.imaginary is in [-1.5, 1.5]. The result is the fractal Julia set that we want. Use at least 20 iterations of the function to create your fractal set.
The value of c will be handed to your program through these two lines of Java (already present in the example code):
fractal_shader.set ("cx", 0.0);
fractal_shader.set ("cy", cos(time) * 0.65);
Since the value of "time" will change, this means your Julia set will change over time.