コード例 #1
0
//--------------------------------------------------------------------------------
// 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;
}