Vector Raytracer::shade(Ray const &ray, int &rayDepth, Intersection const &intersection, Material const &material, Scene const &scene) { // - iterate over all lights, calculating ambient/diffuse/specular contribution // - use shadow rays to determine shadows // - integrate the contributions of each light // - include emission of the surface material // - call Raytracer::trace for reflection/refraction colors // Don't reflect/refract if maximum ray recursion depth has been reached! //!!! USEFUL NOTES: attenuate factor = 1.0 / (a0 + a1 * d + a2 * d * d)..., ambient light doesn't attenuate, nor does it affected by shadow //!!! USEFUL NOTES: don't accept shadow intersection far away than the light position //!!! USEFUL NOTES: for each kind of ray, i.e. shadow ray, reflected ray, and primary ray, the accepted furthest depth are different Vector diffuse(0); Vector ambient(0); Vector specular(0); Vector v = -ray.direction.normalized(); Vector n = intersection.normal.normalized(); Vector reflect = (-v + 2 * v.dot(n) * n).normalized(); for (auto lightIter = scene.lights.begin(); lightIter != scene.lights.end(); lightIter++) { // @@@@@@ YOUR CODE HERE // calculate local illumination here, remember to add all the lights together // also test shadow here, if a point is in shadow, multiply its diffuse and specular color by (1 - material.shadow) Vector l = (lightIter->position - intersection.position).normalized(); Vector r = (-l + 2 * n.dot(l)*n).normalized(); Vector view = (scene.camera.position - intersection.position).normalized(); double d = //(intersection.position - ray.origin).length()+ (lightIter->position - intersection.position).length(); double attenuation = 1.0 / (lightIter->ambient[0] + d*lightIter->attenuation[1] +d *d*lightIter->attenuation[2]); Ray shadowRay = Ray(intersection.position + (lightIter->position - intersection.position).normalized()* 1e-6,(lightIter->position - intersection.position).normalized()); Intersection hit = intersection; bool isShadow = false; Vector delAmbient = material.ambient * lightIter->ambient; Vector delDiffuse = material.diffuse * lightIter->diffuse * max(0.0, n.dot(l)) * attenuation; Vector delSpecular = material.specular * lightIter->specular * pow(max(0.0, r.dot(view)), material.shininess) * attenuation; for (int x = 0; x< scene.objects.size(); x++) { if (scene.objects[x]->intersect(shadowRay, hit)) { isShadow = true; } } if (isShadow) { ambient += delAmbient; diffuse += delDiffuse * (1 - material.shadow); specular += delSpecular * (1 - material.shadow); } else { ambient += delAmbient; diffuse += delDiffuse; specular += delSpecular; } } Vector reflectedLight(0); if ((!(ABS_FLOAT(material.reflect) < 1e-6)) && (rayDepth < MAX_RAY_RECURSION)) { // @@@@@@ YOUR CODE HERE // calculate reflected color using trace() recursively Ray reflect_ray(intersection.position + reflect*1e-6, reflect); double depth = DBL_MAX; trace(reflect_ray, rayDepth, scene, reflectedLight, depth); } return material.emission + ambient + diffuse + specular + material.reflect * reflectedLight; }
Vector Raytracer::shade(Ray const &ray, int &rayDepth, Intersection const &intersection, Material const &material, Scene const &scene) { // - iterate over all lights, calculating ambient/diffuse/specular contribution // - use shadow rays to determine shadows // - integrate the contributions of each light // - include emission of the surface material // - call Raytracer::trace for reflection/refraction colors // Don't reflect/refract if maximum ray recursion depth has been reached! //!!! USEFUL NOTES: attenuate factor = 1.0 / (a0 + a1 * d + a2 * d * d)..., ambient light doesn't attenuate, nor does it affected by shadow //!!! USEFUL NOTES: don't accept shadow intersection far away than the light position //!!! USEFUL NOTES: for each kind of ray, i.e. shadow ray, reflected ray, and primary ray, the accepted furthest depth are different Vector diffuse(0); Vector ambient(0); Vector specular(0); Vector refractedLight(0); for (auto lightIter = scene.lights.begin(); lightIter != scene.lights.end(); lightIter++) { // calculate local illumination here, remember to add all the lights together // also test shadow here, if a point is in shadow, multiply its diffuse and specular color by (1 - material.shadow) Vector newAmbient = (lightIter->ambient * material.ambient); Vector normalI = intersection.normal.normalized(); Vector incomingLight = (lightIter->position - intersection.position).normalized(); float diffuseDot = max(normalI.dot(incomingLight), 0.0); Vector newDiffuse = (diffuseDot * material.diffuse * lightIter->diffuse); Vector reflectedLight = (-2 * (incomingLight.dot(normalI))* normalI + incomingLight).normalized(); Vector viewVector = ray.direction.normalized(); float specularDot = max(viewVector.dot(reflectedLight), 0.0); Vector newSpecular = (pow(specularDot, material.shininess) * material.specular * lightIter->specular); // create shadow ray Intersection shdHit; Ray shadowRay = Ray((intersection.position + (incomingLight * 0.000001)), incomingLight); double lightDist = (lightIter->position - intersection.position).length(); shdHit.depth = lightDist; bool hitShadow = false; for(auto it = scene.objects.begin(); it != scene.objects.end(); ++ it) { Object * curObj = *it; if (curObj->intersect(shadowRay, shdHit)) { hitShadow = true; } } double attFactor = (lightIter->attenuation[0] + lightIter->attenuation[1] * lightDist + lightIter->attenuation[2] * lightDist * lightDist); if (hitShadow) { newSpecular = newSpecular * (1 - material.shadow); newDiffuse = newDiffuse * (1 - material.shadow); } newSpecular = newSpecular / attFactor; newDiffuse = newDiffuse / attFactor; specular += newSpecular; ambient += newAmbient; diffuse += newDiffuse; } Vector reflectedLight(0); if ((!(ABS_FLOAT(material.reflect) < 1e-6)) && (rayDepth < MAX_RAY_RECURSION)) { if (!ray.refracting) { //inside a refracting object // calculate reflected color using trace() recursively Vector normalI = intersection.normal.normalized(); Vector reflectedDir = (-2 * (ray.direction.dot(normalI))* normalI + ray.direction).normalized(); Ray reflectRay = Ray((intersection.position + (reflectedDir * 0.000001)), reflectedDir); double superdepth = DBL_MAX; trace(reflectRay, rayDepth, scene, reflectedLight, superdepth); } } if ((!(ABS_FLOAT(material.refract) < 1e-6)) && (rayDepth < MAX_RAY_RECURSION)) { Vector normalI = intersection.normal.normalized(); double refractn = 1.0; if (ray.refracting) { //inside a refracting object refractn = material.rfrIndex / 1.0; } else { refractn = 1.0 / material.rfrIndex; } double cosI = normalI.dot(ray.direction); double sinT2 = refractn * refractn * (1.0 - cosI * cosI); if (sinT2 <= 1.0) { Vector refractDir = refractn * ray.direction - (refractn + sqrt(1.0 - sinT2)) * normalI; Ray refractRay = Ray((intersection.position + (refractDir * 0.001)), refractDir, !(ray.refracting)); double superdepth = DBL_MAX; trace(refractRay, rayDepth, scene, refractedLight, superdepth); } } return material.emission + ambient + diffuse + specular + material.reflect * reflectedLight + material.refract * refractedLight; }