Color refraction_shader::Shade( const Scene &scene, const HitInfo &hit ) const{    
	  
	if(gen >= max_depth)
		return scene.envmap->Shade(hit.ray);

	if( mat->emission != black )
		if (_ray.type == indirect_ray) //turnign off the light
			return black;
		else
			return mat->emission; //this si direct sample, so return illum of the light
	
	if(mat->reflectivity != black && _ray.type == indirect_ray)
		return black;
		
	Vec3   O = _ray.origin;
	Vec3   P = hit.point;
	Vec3   N = hit.normal;
	Vec3   E = Unit( O - P );
	Vec3   R = Unit( ( 2.0 * ( E * N ) ) * N - E );
	if( E * N < 0.0 ) N = -N; //flip the normal to make it point into the space of the ray origin

	if(mat->translucency != black ){
		Ray rr = obj->getRefracetedRay(_ray,P,N);
		if(rr.direction!=Vec3(0,0,0)) 
			return scene.Trace(rr)*mat->translucency 
			+ scene.Trace(obj->getReflectedRay(_ray,P,N))*(white-mat->translucency);
		else return black;//this is TIR even after 4 level of internal reflections
	}
	
	unsigned k = 1,n = 1;
		
	if(gen == 1 ){ // rays of tree depth = 1
		n = numDirectRays;
		k = numIndirectRays;
	}

	Color color = mat->diffuse * mat->ambient;

	Sample *dSamples = new Sample[n*n];
	unsigned numSamples;
	HitInfo dHit;		
	Ray dRay,iRay;		
	unsigned Y = scene.NumLights() ;

	for( unsigned i = 0; i < Y; i++ ){
		const Object *light = scene.GetLight(i);
		numSamples = light->GetSamples (hit.point, hit.normal, dSamples, n);
			//#pragma omp parallel for 
		for(unsigned j=0;j<numSamples ;j++){
			dRay.origin = hit.point + Unit(N)*10E-4;
			dRay.direction = Unit( dSamples[j].P - hit.point );
			dRay.generation = gen + 1; //next level in tree
			dHit.ray = dRay;
			dHit.distance = Infinity;
			dRay.type = _ray.type;
			if(scene.Cast(dRay,dHit))
				if( dHit.object == light){
					color += max( 0, dRay.direction*Unit(N) )*
							mat->diffuse*
							light->material->emission*dSamples[j].w/Pi;
					if( mat->Phong_exp !=0 && mat->specular != black) 
							//this si handling specularity
						color += (white-mat->reflectivity)* 
							pow( max( dRay.direction*R,0), mat->Phong_exp) * 
							mat->specular*light->material->emission*dSamples[j].w;
					}
				else if(dHit.object->material->translucency != black){
					//hit a tranclusive surface, so cast the transmitted ray
					Ray rr = dHit.object->getRefracetedRay(dRay,dHit.point, dHit.normal);
					HitInfo rrHit;
					rrHit.distance = Infinity;
					rrHit.ray = rr;
					if(scene.Cast(rr,rrHit))
						if(rrHit.object == light)
							color += max( 0, dRay.direction*Unit(N) )*
							mat->diffuse*
							light->material->emission*dSamples[j].w/Pi;
					if( mat->Phong_exp !=0 && mat->specular != black)
						color += (white-mat->reflectivity)*
							pow( max( dRay.direction*R,0), mat->Phong_exp) * 
							mat->specular*light->material->emission*dSamples[j].w;
					
					}
				}
		 
	}	
	
	if(mat->reflectivity == black){
		//sample hmisphere (stratified)
		if(max_depth > 2){
			Sample*	iSamples = new Sample[k*k];
			numSamples = SampleProjectedHemisphere (hit.point, hit.normal, iSamples, k);
			//#pragma omp parallel for
			for(unsigned j = 0; j < numSamples ;j++){
				iRay.origin = hit.point + Unit(N)*10E-4; 
				iRay.from = obj;
				iRay.direction = Unit( hit.point - iSamples[j].P );
				iRay.generation = gen+ 1;
				iRay.type = indirect_ray;
				color += (mat->diffuse*iSamples[j].w*scene.Trace(iRay))/TwoPi;
			}
			delete [] iSamples;
			iSamples = NULL;
		}
	}
	else{
		
		Ray rr;
		rr.origin = P+ N*10E-4;
		rr.direction = R;
		rr.from = obj;
		rr.ignore = NULL;
		rr.generation = gen+1;
		color = color*(white - mat->reflectivity);
		color += mat->reflectivity*scene.Trace(rr);
	}

	

	delete [] dSamples;
	dSamples = NULL;
	return color; 
	

}
Пример #2
0
// Shade assigns a color to a point on a surface, as it is seen
// from another point.  The coordinates of these points, the normal
// of the surface, and the surface material are all recorded in the
// HitInfo structure.  The shader will typically make calls to Trace
// to handle shadows and reflections.
Color Raytracer::Shade(const HitInfo &hit, const Scene &scene, int max_tree_depth)
{
	Color color = { 0.0f, 0.0f, 0.0f };
	Vec3 point = hit.geom.point + hit.geom.normal*Epsilon;
	HitInfo hitObstacle = hit;
	Ray ray, ray2;
	Color diffuse = Color(0,0,0), specular = Color(0,0,0);
	Color direct = Color(0,0,0), indirect = Color(0,0,0);
	Sample lightPoint;

	Vec3 V;
	Color irradiant = Color(0,0,0);
	int espec = 0;
	Color indirect_hemisphere = Color(0, 0, 0), indirect_lobe = Color(0, 0, 0);

	//if (max_tree_depth >= 0) {

		if (hit.material.Emitter()) {
			return hit.material.m_Diffuse;
		}else{
			for (Object *object = scene.first; object != NULL; object = object->next)
			{

				if (object->material.Emitter() == true)
				{
					lightPoint = object->GetSample(hit.geom.point, hit.geom.normal);
					ray.origin = hit.geom.point;

					//lightPoint.P = lightPoint.P + hit.geom.normal*Epsilon;
					ray.direction = Unit(lightPoint.P - hit.geom.point);
					hitObstacle.geom.distance = Length(lightPoint.P - point);

					V = Unit(hit.geom.origin - hit.geom.point);
						Vec3 N = (hit.geom.normal);
						Vec3 H = Unit(V + ray.direction);
						//V = Unit(hit.geom.origin - hit.geom.point);
						Vec3 L = (-ray.direction);// Unit(point - lightPoint.P);
						Vec3 R = Unit(Reflection(-L, N));//Unit((2*N*(N*L))-L);

					espec = hit.material.m_Phong_exp;

					double c = (L*H);
					double g = sqrt((pow(1.4 / 1, 2.0))+ pow(c,2)-1);
					Color f0 = hit.material.m_Specular;


					double F = (f0.red + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.green + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.blue+(1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)));
					//double F = (1 / 2)*((pow(g - c, 2))/(pow(g + c, 2)))*(1+pow((c*(g+c)-1),2)/ (1 + pow((c*(g - c) + 1), 2)));
					double D = ((espec + 2) / (2 * Pi))*(pow((H*N), espec));
					//double D = 1/(sqrt(2*Pi))
					double G = min(min(1.0, (2 * (N*H)*(N*V)) / (V*H)), (2 * (N*H)*(N*L)) / (L*H));
					if (G < 0) G = 0;
					if (D < 0) D = 0;
					if (F < 0) F = 0;

					if (!Cast(ray, scene, hitObstacle)) {
						

						if (N * L > 0) {
							diffuse = (N*L)*hit.material.m_Diffuse/Pi;
						}
						else {
							diffuse = Color(0.0, 0.0, 0.0);
						}

						irradiant = object->material.m_Emission*(lightPoint.w);
						
						if ((R*V) > 0 && hit.material.m_Phong_exp > 0) {
							specular = /*(espec + 2)/(2*Pi) * pow((R*V), espec)*/(F*D*G / (4 * (N*L)*(N*V)))*hit.material.m_Specular;
						}
						else {
							specular = Color(0.0, 0.0, 0.0);
						}
						direct += (diffuse + specular)*irradiant;
					}
				}
			}
			if (hit.material.m_Phong_exp > 0) {
				Vec3 N = (hit.geom.normal);
				Vec3 L = Unit(-ray.direction);
				V = -Unit(hit.geom.point - hit.geom.origin);
				Vec3 R = Unit(Reflection(-V, N));
				Vec3 H = Unit(V + ray.direction);
				double c = (L*H);
				double g = sqrt((pow(1.4 / 1, 2.0)) + pow(c, 2) - 1);
				Color f0 = hit.material.m_Specular;

				double F = (f0.red + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.green + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.blue + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)));
				//double F = (1 / 2)*((pow(g - c, 2))/(pow(g + c, 2)))*(1+pow((c*(g+c)-1),2)/ (1 + pow((c*(g - c) + 1), 2)));
				double D = ((espec + 2) / (2 * Pi))*(pow((H*N), espec));
				double G = min(min(1.0, (2 * (N*H)*(N*V)) / (V*H)), (2 * (N*H)*(N*L)) / (L*H));
				if (G < 0) G = 0;
				if (D < 0) D = 0;
				if (F < 0) F = 0;


				float phong_exp = hit.material.m_Phong_exp;
				ray2.origin = point;

				Sample sample_hemisphere = SampleProjectedHemisphere(N);
				ray2.direction = Unit(sample_hemisphere.P);
				//ray2.no_emitters = true;
				indirect_hemisphere = Trace(ray2, scene, max_tree_depth-1)*  hit.material.m_Diffuse;

				Sample specular_sample = SampleSpecularLobe(R, phong_exp);
				ray2.direction = Unit(specular_sample.P);
				indirect_lobe = Trace(ray2, scene, max_tree_depth - 1)*F*D*G / (4 * (N*L)*(N*V));// *hit.material.m_Specular;

				indirect = indirect_hemisphere + indirect_lobe;// *(F*D*G / (4 * (N*L)*(N*V)));
			}
			
			return (direct) + indirect;
		}
	//}
}