I've created a simple applet that makes a "fake" sphere, and lets you shade it pixel by pixel. Your rendering routine needs to look at the xyz and normal vectors at each sample, and implement the Phong shading model to make a picture.
Please use the values for ambient/diffuse/specular shading, as well as the two light sources in the listing below. Your final result should look something like this:
Extra credit: Account for lights at different distances by implementing a reasonable light attenuation model.
import java.awt.*; import java.awt.image.*; import java.util.*; public class ShadingApplet extends GenericApplet { public void render(Graphics g) { if (!damage) return; int width = bounds().width; int height = bounds().height; // fill the background with middle gray g.setColor(new Color(128,128,128)); g.fillRect(0, 0, width, height); // loop over all pixels int x0 = width/2; int y0 = height/2; int r = Math.min(width,height)/2; for (int x = x0-r ; x < x0+r ; x++) for (int y = y0-r ; y < y0+r ; y++) { // compute x and y of the normal double[] normal = {(double)(x-x0)/r, -(double)(y-y0)/r, 0}; // if pixel is on the sphere double rr = normal[0]*normal[0] + normal[1]*normal[1]; if (rr < 1.) { // compute z of the normal, and do shading normal[2] = Math.sqrt(1. - rr); double rgb[] = new double[3]; shadePixel(normal, normal, rgb); // adjust for over-saturated colors, and write the pixel for (int j = 0 ; j < 3 ; j++) if (rgb[j] > 1.) for (int k = 0 ; k < 3 ; k++) rgb[k] /= rgb[j]; g.setColor(new Color((float)rgb[0],(float)rgb[1],(float)rgb[2])); g.drawLine(x,y,x,y); } } } double ambient[] = {.1,.1,.1}; // Red,Green,Blue double diffuse[] = {.9,0,0}; // Red,Green,Blue double specular[] = {1,1,1,10}; // Red,Green,Blue,SpecularPower double light[][][] = { {{ .6, .6,.5}, {.8,.8,.8}}, // [ X,Y,Z ] , [ Red,Green,Blue] ] {{-.8,0 ,.6}, {.2,.2,.3}}, }; public void shadePixel(double[] xyz, double[] normal, double[] rgb) { /* YOUR CODE GOES HERE */ } }