Пример #1
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
vec3f RayTracer::traceRay( Scene *scene, const ray& r, const vec3f& thresh, int depth )
{
	isect i;
	vec3f colorC;
	if (scene->intersect(r, i)) {
		// YOUR CODE HERE

		// An intersection occurred!  We've got work to do.  For now,
		// this code gets the material for the surface that was intersected,
		// and asks that material to provide a color for the ray.  

		// This is a great place to insert code for recursive ray tracing.
		// Instead of just returning the result of shade(), add some
		// more steps: add in the contributions from reflected and refracted
		// rays.

		const Material& m = i.getMaterial();
		vec3f intensity = m.shade(scene, r, i);
		if (depth == 0) return intensity;
		if (thresh.length() < AdaptiveThreshold) return intensity;

		vec3f Qpt = r.at(i.t);
		vec3f minusD = -1 * r.getDirection();
		vec3f cosVector = i.N * (minusD * i.N);
		vec3f sinVector = cosVector + r.getDirection();
		vec3f newThresh = thresh;

		// Reflected Ray
		if (!m.kr(i).iszero())
		{
			vec3f reflectedDirection = cosVector + sinVector;
			reflectedDirection.normalize();
			ray reflectedRay(Qpt, reflectedDirection, ray::REFLECTION);
			newThresh = prod(newThresh, i.getMaterial().kr(i)); // change the threshold value
			intensity = intensity + prod(m.kr(i), traceRay(scene, reflectedRay, newThresh, depth - 1));
		}

		//Refracted Ray
		if (!m.kt(i).iszero())
		{
			double cosineAngle = acos(i.N * r.getDirection()) * 180 / M_PI;
			double n_i, n_r;
			double criticalAngle = 360;
			int iDirection;
			// bool goingIn = true;
			// double cosThetaI = 0;
			if (cosineAngle > 90) // Coming into an object from air
			{
				n_i = 1;
				n_r = m.index(i);
				iDirection = 1;
				// cosThetaI = i.N * -1 * r.d;
			}
			else // Going out from object to air
			{
				n_i = m.index(i);
				n_r = 1;
				// goingIn = false;
				// cosThetaI = i.N * r.d;
				iDirection = -1;
			}
			
			double n = n_i / n_r;
			if (1 - n * n * (1 - (minusD * i.N) * (minusD * i.N)) > 0.0) // NO total internal refraction
			{
				vec3f sinT = n * sinVector;
				// vec3f cosT = (-1 * i.N) * sqrt(1 - sinT*sinT);
				// not sure if there are any differences between the two eqn, please check!!!!!!
				vec3f cosT = (-1 * i.N) * sqrt(1 - n * n * (1 - (minusD * i.N) * (minusD * i.N)));
				vec3f refractedDirection = cosT + iDirection*sinT;
				refractedDirection.normalize();
				ray refractedRay(Qpt, iDirection * refractedDirection, ray::REFRACTION);
				newThresh = prod(newThresh, i.getMaterial().kt(i)); // change the threshold value
				intensity = intensity + prod(m.kt(i), traceRay(scene, refractedRay, newThresh, depth - 1));
			}
		}
		colorC = intensity;
	}
	else {
		// No intersection.  This ray travels to infinity, so we color
		// it according to the background color, which in this (simple) case
		// is just black.
		colorC = vec3f (0.0, 0.0, 0.0);
	}
	return colorC;
}
Пример #2
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
vec3f RayTracer::traceRay( Scene *scene, const ray& r, 
	const vec3f& thresh, int depth )
{
	isect i;

	if( scene->intersectMode( r, i ) ) {
		// YOUR CODE HERE

		// An intersection occured!  We've got work to do.  For now,
		// this code gets the material for the surface that was intersected,
		// and asks that material to provide a color for the ray.  



		// This is a great place to insert code for recursive ray tracing.
		// Instead of just returning the result of shade(), add some
		// more steps: add in the contributions from reflected and refracted
		// rays.

		const Material& m = i.getMaterial();
		vec3f I = m.shade(scene, r, i);
		if (depth >= maxDepth)return I;
		if (thresh.length() < maxThresh-RAY_EPSILON)return I;

		vec3f conPoint = r.at(i.t);
		vec3f normal;
		vec3f Rdir = 2 * (i.N*-r.getDirection()) * i.N - (-r.getDirection());
		//reflection
		ray R = ray(conPoint, Rdir);
		vec3f newThres = prod(thresh, i.getMaterial().kr);
		if (!i.getMaterial().kr.iszero())I += prod(i.getMaterial().kr, traceRay(scene, R, newThres, depth + 1));

		//if not opaque
		if (!i.getMaterial().kt.iszero()){

			bool TIR = false;

			//refraction
			ray T(conPoint, r.getDirection());//without refraction

			bool toAdd = false, toErase = false;
			//if not surface
			if (i.obj->hasInterior()){
				//calculate angle
				//in or out
				double indexA, indexB;
				if (i.N*r.getDirection() > RAY_EPSILON){//out
					if (mediaHistory.empty())indexA = 1.0;
					else indexA = mediaHistory.rbegin()->second.index;

					mediaHistory.erase(i.obj->getOrder());
					toAdd = true;
					if (mediaHistory.empty())indexB = 1.0;
					else {
						indexB = mediaHistory.rbegin()->second.index;
					}
					normal = -i.N;
				}
				else {//in
					if (mediaHistory.empty())indexA = 1.0;
					else indexA = mediaHistory.rbegin()->second.index;
					
					mediaHistory.insert(make_pair(i.obj->getOrder(),i.getMaterial()));
					toErase = true;
					indexB = mediaHistory.rbegin()->second.index;
					normal = i.N;
				}
				double indexRatio = indexA / indexB;
				double cdi = normal*-r.getDirection();
				double sdi = 1 - cdi*cdi;
				double sdt = sdi * indexRatio; //sin delta t
				//TIR
				if (sdt > 1.0 + RAY_EPSILON){
					TIR = true;
				}
				else {
					TIR = false;
					double cdt = sqrt(1 - sdt*sdt);
					vec3f Tdir = (indexRatio*cdi - cdt)*normal - indexRatio*-r.getDirection();
					T = ray(conPoint, Tdir);
				}
			}
			newThres = prod(thresh, i.getMaterial().kt);
			if(!TIR)I += prod(i.getMaterial().kt, traceRay(scene, T, newThres, depth + 1));
			if (toAdd)mediaHistory.insert(make_pair(i.obj->getOrder(), i.getMaterial()));
			if (toErase)mediaHistory.erase(i.obj->getOrder());
		}
		I = I.clamp();

		return I;
	
	} else {
		// No intersection.  This ray travels to infinity, so we color
		// it according to the background color, which in this (simple) case
		// is just black.
		if (!useBackground)return vec3f(0.0, 0.0, 0.0);
		else {
			vec3f axis_x = scene->getCamera()->getU();
			vec3f S = r.getDirection();
			S -= (S*axis_x)*axis_x;
			vec3f axis_z = scene->getCamera()->getLook();
			vec3f sz = (S*axis_z) *axis_z;
			S -= sz;
			vec3f axis_v = scene->getCamera()->getV();
			vec3f axis_y = axis_x.cross(axis_z);
			double dis_v = (S*axis_y);
			S = r.getDirection() - dis_v * axis_v;
			double dis_x = S * axis_x;
			double dis_z = S * axis_z;
			vec3f res = dis_x * axis_x + dis_v * axis_v + dis_z * axis_z;
			return getBackgroundImage(dis_x / dis_z + 0.5, dis_v / dis_z + 0.5);
		}
		
	}
}