Ejemplo n.º 1
0
Vec3f find_color(Ray ray,Hit hit,Group* group,Camera* camera)
{
	int num_lights = sceneParser->getNumLights();
	Vec3f cambient = sceneParser->getAmbientLight();
	if (group->intersect(ray, hit, camera->getTMin()))//撞到了
	{
		Vec3f cobject = hit.getMaterial()->getDiffuseColor();
		Vec3f canswer = cambient * cobject;
		Vec3f clight;
		Vec3f light_dir;
		Vec3f normal_dir = hit.getNormal();
		float distolight;
		for (int i = 0; i < num_lights; i++)
		{
			Light *light = sceneParser->getLight(i);
			//light_dir : the direction to the light
			// 该方法用于获得指向光的方向,光的颜色,和到达光的距离
			light->getIllumination(hit.getIntersectionPoint(), light_dir, clight, distolight);
			//cpixel  =  cambient * cobject + SUMi [ clamped(Li . N) * clighti * cobject ]
			//返回局部光
			canswer = canswer + hit.getMaterial()->Shade(ray, hit, light_dir, clight)*cobject;
			canswer.Clamp();
		}
		return canswer;
	}
	else
		return sceneParser->getBackgroundColor();
}
Ejemplo n.º 2
0
Vec3f RayTracer::shadow(const Vec3f &point,
			const Vec3f &pointOnLight,
			const Face *f,
			const Ray &ray,
			const Hit &hit) const
{
        const Vec3f normal(hit.getNormal());
        const Material *m = hit.getMaterial();

	Vec3f dirToLight = pointOnLight - point;
	dirToLight.Normalize();
	/* If dot product < 0, surface is not facing light */
	if (normal.Dot3(dirToLight) > 0) {
		Ray rayToLight(point, dirToLight);
		Hit hLight;
		bool blocked = CastRay(rayToLight, hLight, false);
		while (std::fabs(hLight.getT()) < SURFACE_EPSILON &&
				std::fabs((pointOnLight - point).Length()) > SURFACE_EPSILON) {
			rayToLight = Ray(rayToLight.pointAtParameter(SURFACE_EPSILON),
					dirToLight);
			blocked = CastRay(rayToLight, hLight, false);
		}
		if (hLight.getT() == FLT_MAX || hLight.getMaterial() != f->getMaterial()) {
			return Vec3f(0, 0, 0);
		}

		const Vec3f lightColor = 0.2 * f->getMaterial()->getEmittedColor() * f->getArea();
		return m->Shade(ray,hit,dirToLight,lightColor,args);
	}
	return Vec3f(0, 0, 0);
}
Ejemplo n.º 3
0
bool Grid::intersect(const Ray &r, Hit &h, float tmin)
{
	MarchingInfo march;
	initialRayMarch(march,r,tmin);

	int currentI = march.GetI();
	int currentJ = march.GetJ();    
	int currentK = march.GetK();
	float currentT = march.GetT();
	int numObjects;
	//Object3DVector currentVector; 绝对不能新建一个Object3DVector,然后把isOpaque的值赋给这个Object3DVector,因为当这个函数结束时,会把Object3DVector销毁,对应的指针指向的对象也会被销毁。
	//当然还有一种方法是定义一个Object3DVector指针
	//printf("i:%d j:%d currentI:%d currentJ:%d currentK:%d\n",i,j,currentI,currentJ,currentK);

	Object3DVector isAlreadyIntersect;

	while(currentI>=0 && currentI<nx && currentJ>=0 && currentJ<ny && currentK>=0 && currentK<nz)
	{
		RayTracingStats::IncrementNumGridCellsTraversed();
		Object3DVector* currentVector = &isOpaque[currentI][currentJ][currentK];
		numObjects = currentVector->getNumObjects();
		//printf("%d %d %d\n",currentI,currentJ,currentK);
		for(int i=0; i<numObjects; ++i)
		{
			//already intersected object don't need intersect again
			if(isAlreadyIntersect.isInside(currentVector->getObject(i)))
				continue;
			RayTracingStats::IncrementNumIntersections();
			currentVector->getObject(i)->intersect(r,h,tmin);
			isAlreadyIntersect.addObject(currentVector->getObject(i));
		}
		if(h.getMaterial()!=NULL && h.getT()>=currentT && h.getT()<=march.GetNext_x() && h.getT()<=march.GetNext_y() && h.getT()<=march.GetNext_z())
		{
			return true;
		}

		march.nextCell();
		currentI = march.GetI();
		currentJ = march.GetJ();
		currentK = march.GetK();
		currentT = march.GetT();  //折射或反射,shadow时,光线圆点会在grid内
	}
	numObjects = others.getNumObjects();
	for(int i=0; i<numObjects; i++)
	{
		others.getObject(i)->intersect(r,h,tmin);
	}
	if(h.getMaterial()!=NULL)   //这里有问题,因为如果没有和平面相交的话,h的material也有可能不是null
		return true;

	return false;
}
Ejemplo n.º 4
0
bool Transform::Intersect(const Ray &r, Hit &h, float tmin) const
{
  bool result = false;
  
  Matrix m = m_matrix;
  if ( m.Inverse() )
    {
      Vec3f org = r.getOrigin();
      Vec3f dir = r.getDirection();
      m.Transform(org);
      m.TransformDirection(dir);
      Ray r2 (dir, org);
      result = m_pObject->Intersect(r2, h, tmin);
      
      if (result)
	{
	  Matrix m1 = m;
	  m1.Transpose();
	  Vec3f n = h.getNormal();
	  m1.TransformDirection(n);
	  n.Normalize();
	  h.set(h.getT(), h.getMaterial(), n, r);
	}
    }
  return result;
}
Ejemplo n.º 5
0
// does the recursive (shadow rays & recursive/glossy rays) work
Vec3f RayTracer::TraceRay(const Ray &ray, Hit &hit, int bounce_count) const
{
        hit = Hit();
        bool intersect = CastRay(ray,hit,false);

        Vec3f answer(args->background_color_linear);

        if (intersect == true) {
                const Material *m = hit.getMaterial();
                assert (m != NULL);

                // rays coming from the light source are set to white, don't bother to ray trace further.
                if (m->getEmittedColor().Length() > 0.001) {
                        answer = Vec3f(1,1,1);
                } else {
                        // ambient light
                        answer = args->ambient_light_linear *
                                 m->getDiffuseColor(hit.get_s(),hit.get_t());

                        // Shadows
                        answer += shadows(ray, hit);

                        // Reflections
                        Vec3f reflectiveColor = m->getReflectiveColor();
                        double roughness = m->getRoughness();
                        if (bounce_count > 0 && reflectiveColor.Length() > MIN_COLOR_LEN) {
                        	answer += reflectiveColor * reflections(ray, hit, bounce_count, roughness);
                        }
                }
        }

        return answer;
}
Ejemplo n.º 6
0
/*
The intersect routine will first transform the ray, 
then delegate to the intersect routine of the contained 
object. Make sure to correctly transform the resulting 
normal according to the rule seen in lecture. You may 
choose to normalize the direction of the transformed ray 
or leave it un-normalized. If you decide not to normalize 
the direction, you might need to update some of your intersection code.
*/
bool Transform::intersect(const Ray &r, Hit &h, float tmin)
{
	Vec3f r0 = r.getOrigin();
	Vec3f rd = r.getDirection();
	Matrix inv;
	matrix.Inverse(inv);
	inv.Transform(r0);
	inv.TransformDirection(rd);
	if (object != NULL)
	{
		//这里的h是有问题的,作如下修改:
		bool judge = object->intersect(Ray(r0,rd), h, tmin);
		Vec3f normal = h.getNormal();
		//这里很奇怪,normal的方向没有修正,然而结果却是对的
		//改了之后反而是错的!!
		//这里确定normal没有错,那么就是之后应用normal的
		//问题
		//好吧,就是这里的问题
		//经过把图形摆正,发现求的法向量没有问题,但是没有单位化…………!
		matrix.TransformDirection(normal);
		normal.Normalize();
		//or:
		//Matrix change,res;
		//matrix.Inverse(change);
		//change.Transpose(res);
		//res.TransformDirection(normal);
		h.set(h.getT(), h.getMaterial(), normal, r);
		return judge;
	}
	return false;
}
void PhotonMapping::TracePhoton(const Vec3f &position, const Vec3f &direction, 
				const Vec3f &energy, int iter) {
  
  if(iter>args->num_bounces){
    return;
  }

  Hit h = Hit();
  Ray R = Ray(position, direction);
  bool intersect = raytracer->CastRay(R, h, false);
  if(!intersect){
    return;
  }
  Material *m = h.getMaterial();
  Vec3f normal = h.getNormal();
  Vec3f point = R.pointAtParameter(h.getT());
  Vec3f opDirec = direction;
  opDirec.Negate();
  opDirec.Normalize();
  Vec3f diffuse = m->getDiffuseColor(), reflec = m->getReflectiveColor();
  double diffuseAnswer = diffuse.x()+diffuse.y()+diffuse.z();
  double reflecAnswer = reflec.x()+reflec.y()+reflec.z();
  double total = reflecAnswer+diffuseAnswer;
  diffuseAnswer /= total;
  reflecAnswer /= total;
  double seed = GLOBAL_mtrand.rand();
  if(seed <= diffuseAnswer && seed >= 0){
    Vec3f newEnergy = energy * diffuse;
    Vec3f newPosition = point;
    Vec3f newDirection = Vec3f(GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand());
    newDirection.Normalize();
    Photon answer = Photon(point,opDirec,newEnergy,iter+1);
    kdtree->AddPhoton(answer);
    TracePhoton(newPosition, newDirection, newEnergy, iter+1);
  }
  else if(seed>diffuseAnswer && seed <= 1){
    Vec3f newEnergy = energy * reflec;
    Vec3f newPosition = point;
    Vec3f newDirection = direction - 2 * direction.Dot3(normal) * normal;
    Photon answer = Photon(point,opDirec,newEnergy,iter+1);
    kdtree->AddPhoton(answer);
    TracePhoton(newPosition, newDirection, newEnergy, iter+1);
  }
  // ==============================================
  // ASSIGNMENT: IMPLEMENT RECURSIVE PHOTON TRACING
  // ==============================================

  // Trace the photon through the scene.  At each diffuse or
  // reflective bounce, store the photon in the kd tree.

  // One optimization is to *not* store the first bounce, since that
  // direct light can be efficiently computed using classic ray
  // tracing.



}
void PhotonMapping::TracePhoton(const Vec3f &position, const Vec3f &direction, 
				const Vec3f &energy, int iter) {


  // ==============================================
  // ASSIGNMENT: IMPLEMENT RECURSIVE PHOTON TRACING
  // ==============================================

  // Trace the photon through the scene.  At each diffuse or
  // reflective bounce, store the photon in the kd tree.

  // One optimization is to *not* store the first bounce, since that
  // direct light can be efficiently computed using classic ray
  // tracing.

  //do ray cast
  Ray r(position,direction*(1/direction.Length()));
  Hit h;
  raytracer->CastRay(r,h,true);
  if (h.getT()>1000)
	  return;
  MTRand mtrand;
  Vec3f refl = h.getMaterial()->getReflectiveColor();
  Vec3f diff = h.getMaterial()->getDiffuseColor();
  double ran=mtrand.rand();
  if (iter==0)
	  ran= mtrand.rand(refl.Length()+diff.Length());
  //std::cout<<iter<<" "<<h.getT()<<" "<<refl.Length()+diff.Length()<<std::endl;
  //send reflective photon
  if (iter<args->num_bounces&&ran<=refl.Length())
	  TracePhoton(r.pointAtParameter(h.getT()),r.getDirection()-2*(r.getDirection().Dot3(h.getNormal()))*h.getNormal(),energy,iter+1);
  else if (iter<args->num_bounces&&ran<=refl.Length()+diff.Length())
	  TracePhoton(r.pointAtParameter(h.getT()),RandomDiffuseDirection(h.getNormal()),energy,iter+1);
  else
  {
	  Photon p(position,direction,energy,iter);
	  kdtree->AddPhoton(p);
  }


}
Ejemplo n.º 9
0
bool Transform::intersect( const Ray& r , Hit& h , float tmin)
{
    Matrix4f iMatrix=TMatrix_.inverse();
	Matrix4f tMatrix=TMatrix_.transposed() ;
    
    //Ray newRay = Ray((iMatrix * Vector4f(r.getOrigin(), 1.0f)).xyz(), (iMatrix* Vector4f(r.getDirection(), 0.0f)).xyz().normalized());
	Ray newRay = Ray((iMatrix * Vector4f(r.getOrigin(), 1.0f)).xyz(), (iMatrix* Vector4f(r.getDirection(), 0.0f)).xyz());
    if(o->intersect(newRay, h , tmin))
    {
    	
		h.set(h.getT(), h.getMaterial(), (iMatrix.transposed() * Vector4f(h.getNormal(), 0.0f)).xyz().normalized());
		return true;

	}

    return false;

}
Ejemplo n.º 10
0
Vec3f RayTracer::shadows(const Ray &ray, const Hit &hit) const
{
	Vec3f answer(0, 0, 0);

	const int num_lights = mesh->getLights().size();
	if (args->num_shadow_samples == 0) {
		for (int i = 0; i < num_lights; ++i) {

			const Face *f = mesh->getLights()[i];
			Vec3f pointOnLight = f->computeCentroid();
			const Vec3f point(ray.pointAtParameter(hit.getT()));
			Vec3f dirToLight = pointOnLight - point;
			dirToLight.Normalize();
			const Vec3f lightColor = 0.2 * f->getMaterial()->getEmittedColor() * f->getArea();
			return hit.getMaterial()->Shade(ray,hit,dirToLight,lightColor,args);
		}
	}

	// ----------------------------------------------
	// add contributions from each light that is not in shadow

	for (int i = 0; i < num_lights; i++) {
		const Face *f = mesh->getLights()[i];
		Vec3f pointOnLight = f->computeCentroid();
		const Vec3f point(ray.pointAtParameter(hit.getT()));

		double answerx = 0, answery = 0, answerz = 0;
		{
			for (int s = 0; s <= args->num_shadow_samples; ++s) {
				const Vec3f sh = shadow(point, pointOnLight, f, ray, hit);
				answerx += sh.x();
				answery += sh.y();
				answerz += sh.z();
				pointOnLight = f->RandomPoint();
			}
		}
		answer += Vec3f(answerx, answery, answerz);
	}
	answer *= static_cast<double>(1) / ((args->num_shadow_samples + 1) * num_lights);
	return answer;
}
Ejemplo n.º 11
0
bool Transform::intersect(const Ray &r, Hit &h, float tmin)
{
	Vec3f original = r.getOrigin();
	Vec3f dir = r.getDirection();

	mReverseMat.Transform(original);
	mReverseMat.TransformDirection(dir);


	Ray transformedRay(original, dir);

	if (mObj->intersect(transformedRay, h, tmin))
	{
        Vec3f normal = h.getNormal();
        Matrix t;
        mReverseMat.Transpose(t);
        t.TransformDirection(normal);
        h.set(h.getT(), h.getMaterial(), normal, r);
        return true;
	}

    return false;
}
Ejemplo n.º 12
0
Vector3f shade(const Ray &ray, const Hit &hit, SceneParser * Scene )
{
	Material * material=hit.getMaterial();

	//need to get a specific diffuse color depending on whether or not we have triangle object
	//and whether or not this triangle object contains a texture 

	//as default set as diffuse color
	Vector3f _diffuseColor=material->getDiffuseColor();

	Vector2f uv; 
	Texture * tex; 

	if(hit.hasTex())
	{
		if((*material).isLoaded())
			cout << "texture should have been loaded" <<endl; 
		else
			cout << "Material is not loaded!" <<endl;

		uv=hit.getTexCoord();
		tex=(*material).getTexture();
		cout << "texture coordinates" << uv[0] << " " << uv[1] <<endl; 
		_diffuseColor=(*tex).getTexel(uv[0],uv[1]); //set diffuse color based on texture map
	}

	Vector3f _specularColor=material->getSpecularColor();
	float _shininess=material->getShininess(); 

        //first we need to figure out where this section of material is located
        Vector3f n=hit.getNormal();
        Vector3f dray=ray.getDirection();
        Vector3f p=ray.pointAtParameter(hit.getT());
        Vector3f c_amb=Scene->getAmbientLight();
        int num=Scene->getNumLights();

        Vector3f color=_diffuseColor*c_amb; //* is direct vector product

        Light * bob;
        Vector3f ldir, col,ref;
        float dist,val,val2;

        //iterate through light sources
        for(int i=0; i<num; i++)
        {
                bob=Scene->getLight(i);
                bob->getIllumination(p,ldir,col,dist);

                //compute contribution from diffuse reflection
                val=ldir.dot(ldir,n);
                if(val<0) //clamp value
                        val=0;
                color=color+_diffuseColor*col*val;

                //compute contribution from specular reflection
                ref=ldir-2*ldir.dot(ldir,n)*n;
                val2=pow(dray.dot(dray,ref),_shininess); //as dray moves off reflection we suppress 
                if(dray.dot(dray,ref)<0) //clamp value
                        val2=0;

                color=color+_specularColor*col*val2;
        }

        return color;
}
Ejemplo n.º 13
0
//没用 weight
Vec3f RayTracer::traceRay(Ray &ray, float tmin, int bounces, float indexOfRefraction, Hit &hit, Grid *grid) const
{
	if(bounces >= max_bounces)
		return Vec3f(0,0,0);
	RayTracingStats::IncrementNumNonShadowRays();
	//Group *group = s->getGroup();
	//group->intersect(ray,hit,tmin);  这里是没用grid的代码
	grid->intersect(ray,hit,tmin);
	
	if(hit.getMaterial()==NULL)
		return s->getBackgroundColor();
	else
	{
		RayTracingStats::IncrementNumShadowRays();
		Vec3f col(0,0,0);
		Vec3f hitPoint = hit.getIntersectionPoint();
		Vec3f tempAmb;
		Vec3f::MultRow(tempAmb,s->getAmbientLight(),hit.getMaterial()->getDiffuse(hitPoint));  //Kd La
		col += tempAmb;
		int lightNumber = s->getNumLights();
		Light *light;
		for(int i=0; i<lightNumber; i++)
		{
			light = s->getLight(i);
			Vec3f lightColor;
			Vec3f dirToLight;
			//Vec3f interPoint = hit.getIntersectionPoint();
			float distanceToLight;
			light->getIllumination(hitPoint,dirToLight,lightColor,distanceToLight);
			if(!castShadowRayGrid(hitPoint-ray.getDirection()*EPSILON,dirToLight,distanceToLight,grid))
			{
				Vec3f tempShade = hit.getMaterial()->Shade(ray,hit,dirToLight,lightColor);  //diffuse specular
				col += tempShade;
			}
		}
		if(hit.getMaterial()->isReflect(hitPoint))  
		{
			Ray rayReflect(mirrorDirection(hit.getNormal(),ray.getDirection()),hitPoint);
			Vec3f tempRefl;
			Hit hit2(1000,NULL,Vec3f(1,1,1));
			Vec3f::MultRow(tempRefl,hit.getMaterial()->getReflect(hitPoint),traceRay(rayReflect,tmin,bounces+1,indexOfRefraction,hit2,grid)); //weight,indexOfRefrection
			col += tempRefl;
		}
		if(hit.getMaterial()->isTransparent(hitPoint))
		{
			bool notTotalReflective;
			Vec3f transmittedDir;
			if(ray.getDirection().Dot3(hit.getNormal())>0) //ray is inside the object
			{
				notTotalReflective = transmittedDirection(hit.getNormal()*(-1.0f),ray.getDirection(),hit.getMaterial()->getIndexOfRefrac(hitPoint),indexOfRefraction,transmittedDir);
			}
			else  //outside
			{
				notTotalReflective = transmittedDirection(hit.getNormal(),ray.getDirection(),indexOfRefraction,hit.getMaterial()->getIndexOfRefrac(hitPoint),transmittedDir);
			}
			
			if(notTotalReflective)
			{
				Ray rayTransparent(transmittedDir,hitPoint);
				Vec3f tempTrans;
				Hit hit3(10000,NULL,Vec3f(1,1,1));
				Vec3f::MultRow(tempTrans,hit.getMaterial()->getTrans(hitPoint),traceRay(rayTransparent,tmin,bounces+1,indexOfRefraction,hit3,grid));
				col += tempTrans;
			}
			else
			{
				Vec3f tempTotalTrans;
				Vec3f::MultRow(tempTotalTrans,hit.getMaterial()->getTrans(hitPoint),hit.getMaterial()->getDiffuse(hitPoint));
				col += tempTotalTrans;
			}
		}
		return col;
	}
}
Ejemplo n.º 14
0
bool Transform::intersect(const Ray &r, Hit &h, float tmin)
{
	float scaler;
	Vec3f d, o, n_ws;
	Ray r1;
	Matrix m;

	r1 = r;
	m = matrix;

	// get the length of direction vector
	scaler = r.getDirection().Length();

	// normalize the direction vector
	d = r1.getDirection();
	d.Normalize();

	// transform the ray
	o = r1.getOrigin();
	m.Transform(o);
	m.TransformDirection(d);

	// Now, Ray origin and direction is transformed to Object Space
	// intersect at Object space
	if (object->intersect(r1, h, tmin) == false)
		return false;

	// transform the hit point and 
	// normal vector back to world space
	//
	// In order to transform the normal vector,
	// let,
	// n_ws,  normal vector in world space,
	// v_ws,  perpendicular to normal in world space,
	// n_os,  normal vector in object space
	// v_os,  perpendicular to normal in object space,
	//
	// given,
	// n_os^T * v_os = 0 and v_ws^T * n_ws = 0
	// 
	// where,
	//   ^T present transport of the vector(matrix)
	//   ^-1 present inverse of the matrix
	//
	// n_os^T * v_os = 0 
	// ==> n_os^T * (M^-1 * M) * v_os = 0 
	// ==> (n_os^T * M^-1) * v_ws = 0
	// and
	//   n_ws * v_ws = 0
	// thus 
	//   n_ws = (n_os^T) * M^-1 = (M^T)^-1 * n_os

	m.Transpose();
	m.Inverse();
	n_ws = h.getNormal();
	m.Transform(n_ws);

	h.set(h.getT() * scaler, h.getMaterial(), n_ws, r);

	return true;
}
Ejemplo n.º 15
0
Vec3f RayTracer::traceRay(Ray &ray, float tmin, int bounces, float weight,
	float indexOfRefraction, Hit &hit) const
{
	//printf("当前已有光线:\n");
	//RayTree::Print();

	Vec3f canswer;
	if (bounces > max_bounces)
		return Vec3f(0.0f, 0.0f, 0.0f); 
	Camera *camera = sceneParser->getCamera();
	Group *group = sceneParser->getGroup();
	int num_lights = sceneParser->getNumLights();
	Vec3f cambient = sceneParser->getAmbientLight();
	//原来最后是这里出了问题,一旦碰到有转换的物体,那么hit带出来的值是
	//转换后的视线看到的值,而非本来视线看到的值
	//所以解决方案是:距离不变,根据距离重新计算焦点
	if (group->intersect(ray, hit, tmin))//撞到了
	{
		if (is_view_ray)
		{
			RayTree::SetMainSegment(ray, 0, hit.getT());
			is_view_ray = false;
		}
		Vec3f cobject = hit.getMaterial()->getDiffuseColor();
		Vec3f hitPoint = hit.getIntersectionPoint();
		//环境光部分
		canswer = cambient * cobject;
		Vec3f clight;//光的颜色
		Vec3f light_dir;//指向光的方向
		Vec3f normal_dir = hit.getNormal();//交点法线向量
		float distolight;//距离光源的距离
		for (int i = 0; i < num_lights; i++)
		{
			Light *light = sceneParser->getLight(i);
			//light_dir : the direction to the light
			// 该方法用于获得指向光的方向,光的颜色,和到达光的距离
			// 第一个参数传递的是焦点信息
			light->getIllumination(hitPoint, light_dir, clight, distolight);

			Ray ray2(hitPoint, light_dir);
			Vec3f init_normal(0, 0, 0);
			Hit hit2(distolight, NULL, init_normal);
			//阴影检测
			if (shadow)
			{
				if (group->intersect(ray2, hit2, tmin)){
					RayTree::AddShadowSegment(ray2, 0, hit2.getT());
					continue;
				}
				RayTree::AddShadowSegment(ray2, 0, hit2.getT());
			}
			//cpixel  =  cambient * cobject + SUMi [ clamped(Li . N) * clighti * cobject ]
			//返回局部光
			canswer = canswer + hit.getMaterial()->Shade(ray, hit, light_dir, clight);
		}

		//printf("当前已有光线:\n");
		//RayTree::Print();

		
		//反射光
		Material *material = hit.getMaterial();
		Vec3f rc = material->getReflectiveColor();
		if (rc.r() > 0 && rc.g() > 0 && rc.b() > 0)
		{
			Vec3f mirrorDir;
			Vec3f incoming = ray.getDirection();
			mirrorDir = mirrorDirection(normal_dir, incoming);
			// The ray weight is simply multiplied by the magnitude of the reflected color
			Ray ray3(hitPoint, mirrorDir);
			Vec3f init_normal(0, 0, 0);
			Hit hit3(distolight, NULL, init_normal);
			//忘记乘以本身的反射光系数%…………
			canswer += traceRay(ray3, tmin, bounces + 1, weight*rc.Length(), indexOfRefraction, hit3)*rc;
			if (bounces + 1 < max_bounces)
				RayTree::AddReflectedSegment(ray3, 0, hit3.getT());
		}

		//printf("当前已有光线:\n");
		//RayTree::Print();


		//从这里开始还都存在问题!!!!!
		//折射光
		Vec3f transmitted;
		Vec3f tc = material->getTransparentColor();
		float index = material->getIndexOfRefraction();
		if (tc.r() > 0 && tc.g() > 0 && tc.b() > 0)
		{
			Vec3f init_normal(0, 0, 0);
			Hit hit4(distolight, NULL, init_normal);
			//在判断折射光的存在之后,要考虑光线的位置:物体内还是物体外
			//这里根据normal和incoming的点积来判断
			Vec3f incoming = ray.getDirection();
			float judge = normal_dir.Dot3(incoming);
			if (judge < 0)//光线在外
			{
				if (transmittedDirection(normal_dir, incoming, 1, index, transmitted))
				{
					Ray ray4(hitPoint, transmitted);
					canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), index, hit4)*tc;
					RayTree::AddTransmittedSegment(ray4, 0, hit4.getT());
				}
			}
			else//光线在内
			{
				normal_dir.Negate();
				if (transmittedDirection(normal_dir, incoming, index, 1, transmitted))
				{
					Ray ray4(hitPoint, transmitted);
					canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), 1, hit4)*tc;
					RayTree::AddTransmittedSegment(ray4, 0, hit4.getT());
				}
			}
		}

		//printf("当前已有光线:\n");
		//RayTree::Print();

	}
	else
		canswer = sceneParser->getBackgroundColor();

	canswer.Clamp();
	return canswer;
}
Ejemplo n.º 16
0
int main( int argc, char* argv[] )
{
    // Fill in your implementation here.
    
    // Things we get from the input arguments
    const char* input_filename;
    int img_height;
    int img_width;
    const char* output_filename;
    int depth_min;
    int depth_max;
    const char* depth_output_filename = NULL;
    const char* normals_output_filename = NULL;
    
    cout << "All variables declared in main..." << endl;

    // This loop loops over each of the input arguments.
    // argNum is initialized to 1 because the first
    // "argument" provided to the program is actually the
    // name of the executable (in our case, "a4").
    for( int argNum = 1; argNum < argc; ++argNum )
    {
        std::cout << "Argument " << argNum << " is: " << argv[argNum] << std::endl;
        
        if (string(argv[argNum]) == "-input")
        {
            assert (argNum+1 <= argc && "Did not specify argument for flag -input"); // make sure there is something after the flag
            input_filename = argv[argNum+1];
            argNum += 1; // move past the flag you just read
        }
        if (string(argv[argNum]) == "-size")
        {
            assert (argNum+2 <= argc && "Did not specify enough arguments for flag -size"); // make sure there is something after the flag
            img_height = atoi(argv[argNum+1]);
            img_width = atoi(argv[argNum+2]);
            argNum += 2;
        }
        if (string(argv[argNum]) == "-output")
        {
            assert (argNum+1 <= argc && "Did not specify argument for flag -output"); // make sure there is something after the flag
            output_filename = argv[argNum+1];
            argNum+=1;
        }
        if (string(argv[argNum]) == "-depth")
        {
            assert (argNum+3 <= argc && "Did not specify enough arguments for flag -depth (should have 3)");
            depth_min = atoi(argv[argNum+1]);
            depth_max = atoi(argv[argNum+2]);
            depth_output_filename = argv[argNum+3];
            argNum+=3;
        }
        if (string(argv[argNum]) == "-normals")
        {
            assert (argNum+1 <= argc && "Did not specify enough arguments for flag -normals (should have 1)");
            normals_output_filename = argv[argNum+1];
            argNum+=1;
        }
        
    }
    
    cout << "Input arguments parsed" << endl;
    // From the handout: Write a main function that:
    //    1) reads the scene (using the parsing code provided)
    //    2) loops over the pixesl in the image plane
    //        3) generates a ray using your camera class
    //        4) intersects it with the high lievel Group that stores the objects of the scene
    //        5) writes the color of the closest intersected object
    
    
    // read the scene using SceneParser
    SceneParser* parser = new SceneParser(input_filename);
    Camera* camera = parser->getCamera();
    Group* group = parser->getGroup();
    Vector3f background_color = parser->getBackgroundColor(); 
    
    
    
    // Loop over pixels in the image plane
    Image* img = new Image(img_width, img_height);
    Image* depth_img = new Image(img_width, img_height);
    Image* normals_img = new Image(img_width, img_height);
    
    cout << "now starting to produce image" << endl;
    cout << "camera's tmin = " << camera->getTMin() << endl;
    for (int j = 0; j < img_height; j++) 
    {
        for (int i = 0; i < img_width; i++) 
        {
//            cout << "for pixel " << i << "," << j << ": ";
            // Generate ray using cmaera class
            float tmin = camera->getTMin();
            Hit hit = Hit(FLT_MAX, NULL, NULL); // is this supposed to be something more...profound?
            
            
            // we want it to map from (-1,-1) to (1,1)
            float x = (2.0/(float)img_width)*(float)i - 1.0;
            float y = (2.0/(float)img_height)*(float)j - 1.0;
            Vector2f pixel = Vector2f(x, y);

            Ray ray = camera->generateRay(pixel);
            
            // intersect the ray with the high level group for the scene
            if (group->intersect(ray, hit, tmin))
            {
                              
                // write color of the closest intersected object
                Material* material = hit.getMaterial();
                if (material->getDiffuseColor()[0] == 1)
                {
                    cout << "color = " << material->getDiffuseColor();
                }
//                cout << "material = " << material << endl;
                if (parser->getNumLights() == 0)
                {
                    Vector3f color = material->getDiffuseColor();
                    if (material->getDiffuseColor()[0] == 1)
                {
                    cout << "writing color = " << material->getDiffuseColor();
                }
                    img->SetPixel(i, j, color); 
                }
                else
                {
                    Vector3f light_color(0,0,0);// we want to iteratively add the light from black
                    for (int k = 0; k < parser->getNumLights(); k++)
                    {
                        Light* light = parser->getLight(k);
                        Vector3f p = ray.pointAtParameter(hit.getT());
                        Vector3f dir;
                        Vector3f col;
                        float distanceToLight = 10.0;
                        light->getIllumination(p, dir, col, distanceToLight); // what should distance to light actually be?                        
                        float coeff = Vector3f::dot(hit.getNormal().normalized(), dir.normalized());
                        light_color += material->getDiffuseColor() * col * coeff;
                                                
                    }
                    if (material->getDiffuseColor()[0] == 1)
                {
                    cout << "writing color = " << material->getDiffuseColor();
                }
                    img->SetPixel(i, j, light_color);
                }
                               
                
                // Visualize Depth (QUESTION: should this be a separate routine?
                // I don't think so because all of the tests also have depth 
                // but this can be commented out for testing if it doesn't work...
                
                if (depth_output_filename != NULL)
                {
                    float d = hit.getT();
//                    d+=1;
//                    d = -d;
//                    cout << "d = " << d << endl;
                    // if t is within the correct range
//                    cout << "depthMin = " << depth_min << ", depth max = " << depth_max << endl;
                    if (d >= depth_min && d <= depth_max)
                    {
                        float depth_val = (d - depth_min)/(depth_max - depth_min);
//                        cout << "depth val = " << depth_val << endl;
                        depth_val = 1-depth_val;
                        depth_img->SetPixel(i, j, Vector3f(depth_val, depth_val, depth_val));
                    }
                }
                
                
                if (normals_output_filename != NULL)
                {
                    Vector3f normal = hit.getNormal();
                    Vector3f fab_norm = Vector3f(fabs(normal[0]), fabs(normal[1]), fabs(normal[2]));
                    normals_img->SetPixel(i, j, fab_norm); // QUESTION: just color the normal?
                }
                    
            } 
            else
            {
//                cout << "writing background color" << endl;
                img->SetPixel(i, j, background_color);
                depth_img->SetPixel(i, j, background_color);
            }
            
            
            
            
            
        }      
    }
    
    
    // Instructions for Depth:
    // Implement a second rendering style to visualize the depth t of
    // objects in the scene. Two input depth values specify the range
    // of depth values which should be mapped to shades of gray in 
    // the visualization. Depth values outside this range = clamped
    
    
    // Instructions for Normals:
    // Implement a new rendering mode, normal visualization
    
    
    
    
    // Write outfiles!
    cout << "images produced, writing outfiles" << endl;
    img->SaveTGA(output_filename);
    if (depth_output_filename != NULL)
    {
        depth_img->SaveTGA(depth_output_filename);
    }
    if (normals_output_filename != NULL)
    {
        normals_img->SaveTGA(normals_output_filename);

    }
           
    

    return 0;
}
Ejemplo n.º 17
0
Vector3f RayTracer::traceRay( Ray& c_ray, float tmin, float refractI, int bounces, Hit& h ) const
{
  h = Hit( FLT_MAX, NULL, Vector3f( 0, 0, 0 ) );
  Vector3f pixelPass = m_scene->getBackgroundColor(c_ray.getDirection());
  bool intersect = g->intersect(c_ray, h , tmin);
  Vector3f pixelIntersect = m_scene->getAmbientLight();
  if(intersect){
    float intersect_t = h.getT();
    Vector3f intersect_p = c_ray.pointAtParameter(intersect_t);
    pixelIntersect = h.getMaterial()->getDiffuseColor()*pixelIntersect;

    for(int l = 0; l < m_scene->getNumLights(); l++){
      //Light
      Light* light = m_scene->getLight(l);
      Vector3f light_dir = Vector3f();
      Vector3f light_col = Vector3f();
      float light_distance = float(0.0f);
      light->getIllumination(intersect_p, light_dir, light_col, light_distance);

      //Shadows
      //cout << "LIGHT_COL:" << light_col.x() << ':' << light_col.y() << ':' << light_col.z(); 
      if(m_shadow){
        Ray test_shade = Ray(intersect_p,light_dir);
        Hit h_shade = Hit(light_distance, NULL, NULL);
        bool intersect_shade = g->intersect(test_shade, h_shade, EPSILON);
        if(h_shade.getT() >= light_distance){
          pixelIntersect += h.getMaterial()->Shade(c_ray,h,light_dir,light_col);
        }
      }
      else{
        pixelIntersect += h.getMaterial()->Shade(c_ray,h,light_dir,light_col);
      }

    }

    if(bounces > 0){
      bool refract = false;
      Vector3f norm = h.getNormal().normalized();

      float nt = h.getMaterial()->getRefractionIndex();

      float R = 1.0;

      //Mirror reflection
      Vector3f mirrorDir = mirrorDirection(norm,c_ray.getDirection().normalized());
      Ray mirrorRay = Ray(intersect_p,mirrorDir);
      Hit mir_h = Hit();
      Vector3f reflColor = traceRay(mirrorRay, EPSILON, refractI, bounces - 1, mir_h);

      Vector3f refrDir = Vector3f();
      Vector3f refrColor = Vector3f();
      if(REFRACTING){
      //Refraction
        if(h.getMaterial()->getRefractionIndex() > 0){

          if (Vector3f::dot(c_ray.getDirection(), norm) > 0)
          {
            nt = 1.0f;
            norm *= -1;
          }
          refract = transmittedDirection(norm, c_ray.getDirection(), refractI, nt, refrDir);

          if(refract){
            Hit refr_h = Hit();
            //cout << "refrDir:" << refrDir.x() << ":" << refrDir.y() << ":" << refrDir.z();
            Ray refrRay = Ray(intersect_p,refrDir);
            refrColor = traceRay(refrRay, EPSILON, nt, bounces - 1, refr_h);

            //Weighting
            float c = 0.0f;
            if(refractI <= nt){
              c = abs(Vector3f::dot(c_ray.getDirection(),norm));
            }
            else{
              c = abs(Vector3f::dot(refrDir,norm));
            }
            float R_0 = pow(((nt - refractI)/(nt + refractI)),2);
            R = R_0 + (1-R_0)*pow((1-c),5);
          }
        }
      }

      pixelIntersect += h.getMaterial()->getSpecularColor()*(R*reflColor + (1-R)*refrColor);
    }
    return pixelIntersect;
  }
  else{
    return pixelPass;
  }
}