package graphics; public class Shader { //toony effect by rounding colors off public static int colorMask = 0; public static double[] shade(Vector3 normal, Material material, Light[] lights, int[] ambient) { Vector3 eye = new Vector3(0, 0, 1); //eye/camera is at the origin return shade(eye, normal, material, lights, ambient); } public static double[] shade(Vector3 eye, Vector3 normal, Material material, Light[] lights, int[] ambient) { //eye.normalize(); double r = 0, g = 0, b = 0; for (int li = 0; li < lights.length; li++) { //colors for this light double lr = 0, lg = 0, lb = 0; //diffuse shading // f is L dot N double fDiff = normal.dotProduct( lights[li].getDirectionVector() ); if (fDiff < 0) fDiff = 0; lr += fDiff * material.diffuseColor[0]; lg += fDiff * material.diffuseColor[1]; lb += fDiff * material.diffuseColor[2]; //specular shading //R = 2*f*N - L //Ls = [rs,gs,bs]max(0, E ∙ R)^p Vector3 R = new Vector3(normal); //copy normal vector R.scale(-2 * fDiff); // r is now -2fN R.add( lights[li].getDirectionVector() ); //r is now L - 2fN R.scale(-1); //R.normalize(); double fSpec = Math.pow(eye.dotProduct(R), material.shininess); //E ∙ R if (fSpec < 0) fSpec = 0; //System.err.println("fSpec = " + fSpec); lr += fSpec * material.specularColor[0]; lg += fSpec * material.specularColor[1]; lb += fSpec * material.specularColor[2]; //factor in light source, but //scale back down (compare 0.5 * 0.5 with (128 * 128)/256) lr *= lights[li].color[0] / 256.0; lg *= lights[li].color[1] / 256.0; lb *= lights[li].color[2] / 256.0; //add the light to object's light r += lr; g += lg; b += lb; } //add ambient component r += ambient[0]; g += ambient[1]; b += ambient[2]; if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; //make it look cartoony by quantizing colors if (colorMask > 0) { r = (int)r & colorMask; g = (int)g & colorMask; b = (int)b & colorMask; } return new double[] {r, g, b}; } }