// Display checker board background MaterialCell checkerBackgroundHit(Ray r, HitRecord hit) { // Find the t value where z = scene.camera.far hit.t = -scene.camera.far / r.dir.z; if (hit.t < 0) // Only put it on the background, not behind the camera too return black; hit.hitP = r.pointAtParameter(hit.t); hit.normal = new Double3D(0, 0, 1); hit.hitP.x = (hit.hitP.x > 0) ? hit.hitP.x : -hit.hitP.x + checkerFreq / 2; hit.hitP.y = (hit.hitP.y > 0) ? hit.hitP.y : -hit.hitP.y + checkerFreq / 2; if (hit.hitP.x % checkerFreq < checkerFreq / 2) // && p.x < scene.camera.windowRight) if (hit.hitP.y % checkerFreq < checkerFreq / 2) // && p.y < scene.camera.windowTop) return white; else return black; else if (hit.hitP.y % checkerFreq < checkerFreq / 2) // && p.y < scene.camera.windowTop) return black; else return white; }
// iPoint is the point of intersection with the surface. DoubleColor shade(Ray ray, HitRecord hit, MaterialCell material, boolean background) { DoubleColor color = new DoubleColor(0.0, 0.0, 0.0, 1.0); // Add ambient light only once color.plus( new DoubleColor( (double) (lights[0].ambient[0] * material.ka.r), (double) (lights[0].ambient[1] * material.ka.g), (double) (lights[0].ambient[2] * material.ka.b), (double) (lights[0].ambient[3] * material.ka.a))); // Assign material color? // Local light or directional? If directional then we need to see if it's shining on the // object if (!background) { double d = 2; // L.distanceTo(hit.hitP); for (int i = 0; i < lights.length; i++) { if (lights[i].lightSwitch == 1) { Double3D L = new Double3D( (double) lights[i].position[0], (double) lights[i].position[1], (double) lights[i].position[2]); L = L.minus(hit.hitP).getUnit(); Ray shadowRay = new Ray(hit.hitP, L); // trace shadow ray to light source // Turn shadows on and shadowRay hit nothing if (!scene.shadows || shadowTrace(shadowRay)) { double LdN = Math.max(0, hit.normal.dot(L)); if (LdN > 0) { // -2(-L.N)N + -L Double3D R = hit.normal.sMult(-2 * hit.normal.dot(L.sMult(-1))).plus(L.sMult(-1)); double RdV = Math.max(0, -R.dot(ray.dir)); // If the light is free add the diffuse light // Intensity (Kd * (LdN) + Ks *(RdV)^(shiny)/(r + k) color.plus( new DoubleColor( (double) (lights[i].diffuse[0] * LdN + lights[i].specular[0] * Math.pow(RdV, material.shiny)) / d, (double) (lights[i].diffuse[1] * LdN + lights[i].specular[1] * Math.pow(RdV, material.shiny)) / d, (double) (lights[i].diffuse[2] * LdN + lights[i].specular[2] * Math.pow(RdV, material.shiny)) / d, 1.0)); // */ } // if(LdN > 0) } // if(!scene.shadows || shadowTrace(shadowRay)) } // if(lights[i].lightSwitch == 1){ } // for // Shiny Phong // If IdN > 0 then we find a reflection // If IdN < 0 then we need -normal if (scene.reflections && (material.reflectivity.r > 0 || material.reflectivity.g > 0 || material.reflectivity.b > 0)) { depth++; // R = I - 2 * (I.N)N Double3D R = new Double3D(); Double3D I = ray.dir; // .sMult(-1.0); Double3D N = hit.normal; // double IdN = I.dot(N); // if (IdN > 0){ // N = N.sMult(-1.0); // IdN = -I.dot(N); // }//*/ R = I.plus(N.sMult(-2.0 * I.dot(N))); Ray reflect = new Ray(hit.hitP, R); DoubleColor reflection = trace(reflect); // Scale by distance? // reflection.scale( 1 / reflect.origin().distanceTo(hit.hitP)); reflection.r = reflection.r * material.reflectivity.r; reflection.g = reflection.g * material.reflectivity.g; reflection.b = reflection.b * material.reflectivity.b; color.plus(reflection); depth--; } if (scene.refractions && (material.refractivity.r > 0 || material.refractivity.g > 0 || material.refractivity.b > 0)) // */ { depth++; Ray refract = new Ray(hit.hitP, ray.dir); if (hit.index == ray.r.objectNum) // Hit the object we're already in { // Pop the n off the stack refract.r = ray.r; // Swap the refraction indices double temp = refract.r.n; refract.r.n = refract.r.prevR.n; refract.r.prevR.n = temp; } else // Otherwise we hit a new object push this n onto the stack and get mat index { refract.r.prevR = ray.r; refract.r.n = material.refractiveIndex; refract.r.objectNum = hit.index; } if (transmissionDirection(ray, hit, refract)) { DoubleColor refraction = trace(refract); refraction.r = refraction.r * material.refractivity.r; refraction.g = refraction.g * material.refractivity.g; refraction.b = refraction.b * material.refractivity.b; // Scale for distance? color.plus(refraction); } depth--; } } return color; }