//-------------------------------------------------------------------------------- // Shader //-------------------------------------------------------------------------------- Vector_3D<double> Phong_Shader:: Shade_Surface(const Ray& ray,const Object& intersection_object,const Vector_3D<double>& intersection_point,const Vector_3D<double>& same_side_normal) const { typedef Vector_3D<double> TV; TV color; //add diffuse + ambient + specular and return color // calculate vector towards the viewer TV view_ray = (world.camera.position - intersection_point).Normalized(); TV normal = same_side_normal.Normalized(); // Regardless of shadows, add ambiant to color // Ambient lighting TV ambient = color_ambient*world.lights[0]->Emitted_Light(ray); color += ambient; // get vectors towards the two light sources TV l_ray1 = (world.lights[0]->position - intersection_point).Normalized(); TV l_ray2 = (world.lights[1]->position - intersection_point).Normalized(); //Create Ray objects to "Cast" shadow rays Ray light_ray1(intersection_point, l_ray1); Ray light_ray2(intersection_point, l_ray2); light_ray1.endpoint += normal*0.05; light_ray2.endpoint += normal*0.05; vector<Ray> light_vec; // store rays in vector for looping light_vec.push_back(light_ray1); light_vec.push_back(light_ray2); if (world.enable_shadows == true) { //count the number of obstructed light rays int num_shadows = 0; for (unsigned int i=0; i<light_vec.size(); i++) { // create dummy object to access background color TV dummy; const Object* obj = new Sphere(dummy, 1.0); obj = world.Closest_Intersection(light_vec[i]); delete obj; if (light_vec[i].semi_infinite == false) num_shadows++; } // if one lightray intersects an object, delete from further calcs if (num_shadows == 1) { if (light_vec[0].semi_infinite == false) light_vec.erase(light_vec.begin()); else light_vec.erase(light_vec.begin()+1); } // if both intersect, return ambiant light if (num_shadows == 2) return color; } // Diffuse TV diffuse; for (unsigned int i = 0; i < light_vec.size(); i++) { double l_n = TV::Dot_Product(light_vec[i].direction, normal); TV Ld = world.lights[i]->Emitted_Light(ray)*max((double)0, l_n); diffuse += color_diffuse*Ld; } //Spectral TV specular; for (unsigned int i = 0; i < light_vec.size(); i++) { TV reflected_ray = (normal*2*(TV::Dot_Product(light_vec[i].direction, normal))) - light_vec[i].direction; reflected_ray.Normalize(); double theta = max((double)0, TV::Dot_Product(reflected_ray, view_ray)); theta = pow(theta, specular_power); TV Ls = world.lights[0]->Emitted_Light(ray)*theta; specular += color_specular*Ls; } color += diffuse + specular; return color; }