Vector_3D<double> Sphere:: Normal(const Vector_3D<double>& location) const { Vector_3D<double> normal; normal = (location - center); normal.Normalize(); return normal; }
Vector_3D<double> Sphere:: Normal(const Vector_3D<double>& location) const { Vector_3D<double> normal; normal.x = (location.x - center.x); normal.y = (location.y - center.y); normal.z = (location.z - center.z); normal.Normalize(); return normal; }
//-------------------------------------------------------------------------------- // 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; }
// The operator % will be used as cross product operator Vector_3D operator%(const Vector_3D &vect) const { return Vector_3D(y*vect.getZ() - z*vect.getY(), x*vect.getZ() - z*vect.getX(), x*vect.getY() - y*vect.getX()); }
// The operator * will be used as dot product operator double operator*(const Vector_3D &vect) const { return x*vect.getX() + y*vect.getY() + z*vect.getZ(); }
Vector_3D operator-(const Vector_3D &vect) const { return Vector_3D(x-vect.getX(), y-vect.getY(), z-vect.getZ()); }
Vector_3D operator+(const Vector_3D &vect) const { return Vector_3D(x+vect.getX(), y+vect.getY(), z+vect.getZ()); }
//-------------------------------------------------------------------------------- // 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 { Vector_3D<double> color; Vector_3D<double> ambientCoefficient = color_ambient; Vector_3D<double> diffuseReflectance = color_diffuse; // TODO: determine the color //compute each R G B value seperately //ambient ambientCoefficient.x *= world.lights.at(0)->Emitted_Light(ray).x; ambientCoefficient.y *= world.lights.at(0)->Emitted_Light(ray).y; ambientCoefficient.z *= world.lights.at(0)->Emitted_Light(ray).z; color += ambientCoefficient; for (unsigned i = 0; i < world.lights.size(); ++i) { //test for shadows Vector_3D<double> lightVector = (((world.lights.at(i))->position)-intersection_point); //tempray Ray tempRay; tempRay.endpoint = intersection_point; tempRay.direction = lightVector; tempRay.direction.Normalize(); tempRay.t_max = 999999; tempRay.semi_infinite = true; bool shadowDetected = false; for (unsigned j = 0; j < world.objects.size(); ++j) { ////calculate if object intersects if (world.objects.at(j)->Intersection(tempRay)) { if (!(tempRay.current_object == &intersection_object)) { shadowDetected = true; } } } if (!(world.enable_shadows && shadowDetected)) { Vector_3D<double> normal = intersection_object.Normal(intersection_point); //diffuse shading Vector_3D<double> diffuseIntensity = world.lights.at(i)->Emitted_Light(ray); lightVector.Normalize(); double dotProduct = lightVector.x*normal.x + lightVector.y*normal.y + lightVector.z*normal.z; if (dotProduct < 0) { dotProduct = 0; } // cout << "RED DIFFUSE INTENSITY: " << diffuseReflectance.x*(diffuseIntensity) << endl; color.x += dotProduct*diffuseReflectance.x*(diffuseIntensity.x); color.y += dotProduct*diffuseReflectance.y*(diffuseIntensity.y); color.z += dotProduct*diffuseReflectance.z*(diffuseIntensity.z); //specular shading Vector_3D<double> eyeVector = ray.endpoint - intersection_point; eyeVector.Normalize(); Vector_3D<double> tempH = lightVector+eyeVector; tempH.Normalize(); double max = (tempH.x*same_side_normal.x+tempH.y*same_side_normal.y+tempH.z*same_side_normal.z); if (max < 0) { max = 0; } color.x += color_specular.x*(world.lights.at(i)->Emitted_Light(ray).x)*pow(max,specular_power); color.y += color_specular.y*(world.lights.at(i)->Emitted_Light(ray).y)*pow(max,specular_power); color.z += color_specular.z*(world.lights.at(i)->Emitted_Light(ray).z)*pow(max,specular_power); } } return color; }