Пример #1
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;
	}
}
Пример #2
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;
}
Пример #3
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;
  }
}