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 */
}
}