Homework 7, due Wednesday, April 14

Build a Phong shading module. For this assignment you can just use a simple fake geometry, consisting of a sphere.

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:

After you have that much working, try making your own surface color/specularity and light sources.

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