Example #1
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;
}
Example #2
0
bool QBVHAccel::Intersect(const Ray *ray, RayHit *rayHit) const {
  //------------------------------
  // Prepare the ray for intersection
  QuadRay ray4(*ray);
  __m128 invDir[3];
  invDir[0] = _mm_set1_ps(1.f / ray->d.x);
  invDir[1] = _mm_set1_ps(1.f / ray->d.y);
  invDir[2] = _mm_set1_ps(1.f / ray->d.z);

  int signs[3];
  ray->GetDirectionSigns(signs);

  //------------------------------
  // Main loop
  int todoNode = 0; // the index in the stack
  int32_t nodeStack[64];
  nodeStack[0] = 0; // first node to handle: root node

  while (todoNode >= 0) {
    // Leaves are identified by a negative index
    if (!QBVHNode::IsLeaf(nodeStack[todoNode])) {
      QBVHNode &node = nodes[nodeStack[todoNode]];
      --todoNode;

      // It is quite strange but checking here for empty nodes slows down the rendering
      const int32_t visit = node.BBoxIntersect(ray4, invDir, signs);

      switch (visit) {
      case (0x1 | 0x0 | 0x0 | 0x0):
        nodeStack[++todoNode] = node.children[0];
        break;
      case (0x0 | 0x2 | 0x0 | 0x0):
        nodeStack[++todoNode] = node.children[1];
        break;
      case (0x1 | 0x2 | 0x0 | 0x0):
        nodeStack[++todoNode] = node.children[0];
        nodeStack[++todoNode] = node.children[1];
        break;
      case (0x0 | 0x0 | 0x4 | 0x0):
        nodeStack[++todoNode] = node.children[2];
        break;
      case (0x1 | 0x0 | 0x4 | 0x0):
        nodeStack[++todoNode] = node.children[0];
        nodeStack[++todoNode] = node.children[2];
        break;
      case (0x0 | 0x2 | 0x4 | 0x0):
        nodeStack[++todoNode] = node.children[1];
        nodeStack[++todoNode] = node.children[2];
        break;
      case (0x1 | 0x2 | 0x4 | 0x0):
        nodeStack[++todoNode] = node.children[0];
        nodeStack[++todoNode] = node.children[1];
        nodeStack[++todoNode] = node.children[2];
        break;
      case (0x0 | 0x0 | 0x0 | 0x8):
        nodeStack[++todoNode] = node.children[3];
        break;
      case (0x1 | 0x0 | 0x0 | 0x8):
        nodeStack[++todoNode] = node.children[0];
        nodeStack[++todoNode] = node.children[3];
        break;
      case (0x0 | 0x2 | 0x0 | 0x8):
        nodeStack[++todoNode] = node.children[1];
        nodeStack[++todoNode] = node.children[3];
        break;
      case (0x1 | 0x2 | 0x0 | 0x8):
        nodeStack[++todoNode] = node.children[0];
        nodeStack[++todoNode] = node.children[1];
        nodeStack[++todoNode] = node.children[3];
        break;
      case (0x0 | 0x0 | 0x4 | 0x8):
        nodeStack[++todoNode] = node.children[2];
        nodeStack[++todoNode] = node.children[3];
        break;
      case (0x1 | 0x0 | 0x4 | 0x8):
        nodeStack[++todoNode] = node.children[0];
        nodeStack[++todoNode] = node.children[2];
        nodeStack[++todoNode] = node.children[3];
        break;
      case (0x0 | 0x2 | 0x4 | 0x8):
        nodeStack[++todoNode] = node.children[1];
        nodeStack[++todoNode] = node.children[2];
        nodeStack[++todoNode] = node.children[3];
        break;
      case (0x1 | 0x2 | 0x4 | 0x8):
        nodeStack[++todoNode] = node.children[0];
        nodeStack[++todoNode] = node.children[1];
        nodeStack[++todoNode] = node.children[2];
        nodeStack[++todoNode] = node.children[3];
        break;
      }
    } else {
      //----------------------
      // It is a leaf,
      // all the informations are encoded in the index
      const int32_t leafData = nodeStack[todoNode];
      --todoNode;

      if (QBVHNode::IsEmpty(leafData))
        continue;

      // Perform intersection
      const u_int nbQuadPrimitives = QBVHNode::NbQuadPrimitives(leafData);

      const u_int offset = QBVHNode::FirstQuadIndex(leafData);

      for (u_int primNumber = offset; primNumber < (offset
          + nbQuadPrimitives); ++primNumber)
        prims[primNumber].Intersect(ray4, *ray, rayHit);
    }//end of the else
  }

  return !rayHit->Miss();
}