Esempio n. 1
0
const ColorRGB Scene3D::traceRay(const Ray& ray, int depth) const
{

	float closest_t_value = NO_INTERSECT;
	const SceneObject* closest_object = findClosest(ray, closest_t_value);

	if (closest_object == 0)
		return ColorRGB(0,0,0);

	ColorRGB retColor(0,0,0);


	for (int i = 0; i < lights.size(); i++)
	{
		Vector3D normL = ((*lights[i]).get_position()-ray.getPointAt(closest_t_value)).normalize();
		Vector3D normN = (*closest_object).surface_normal(ray.getPointAt(closest_t_value));

		retColor += (*lights[i]).get_color()*(*closest_object).get_color()*std::max((normL*normN),float(0));
		
		if (depth < 6 && (*closest_object).get_reflectivity() > 0)
		{
				Ray reflected_ray = ray.reflect(ray.getPointAt(closest_t_value), (*closest_object).surface_normal(ray.getPointAt(closest_t_value)));
				ColorRGB reflection_color = traceRay(reflected_ray, depth+1);
				retColor+= (*closest_object).get_reflectivity()*reflection_color;
		}
		
	}	


	return retColor;
}
Esempio n. 2
0
void Controller::OnMouseMove(Flags nFlags, int x, int y)
{
	Point point(x,y);

	if (nFlags == LBUTTON)
	{
		Vec3 r;

		r.x = -(Float)(point.x - mouse.x)/3;
		r.y = (Float)(point.y - mouse.y)/3;

		r = cross(r, Vec3(0,0,1));

		Matrix rot = Matrix::Rotation( r.normalized(), r.getLen());
		m_Rotation = m_Rotation * rot;
	}

	if (nFlags == (LBUTTON|RBUTTON)  )
	{
		Vec3 r;

		r.x = -(Float)(point.x - mouse.x)/3;
		r.y = (Float)(point.y - mouse.y)/3;

		r = cross(r, Vec3(0,0,1));

		Matrix rot = Matrix::Rotation( r.normalized(), r.getLen());
		m_Rotation2 = m_Rotation2 * rot;
	}

	if (nFlags == RBUTTON )
	{
		Vec3 n = transform(Vec3(0,0,-1), m_Rotation.getInverted() );
		n = n.normalized();

		Plane ebene = Plane(n.x, n.y, n.z, 0);

		Ray a = getViewport().DPtoRay(mouse.x, mouse.y);
		Ray b = getViewport().DPtoRay(point.x, point.y);

		Float ta = 0, tb = 0;
		ebene.getIntersectionWithLine(a.getOrigin(), a.getPointAt(1), ta);
		ebene.getIntersectionWithLine(b.getOrigin(), b.getPointAt(1), tb);

		Vec3 d = a.getPointAt(ta) - b.getPointAt(tb);

		m_Translation = m_Translation + transform(d, m_Rotation );
	}

	mouse = point;
}
Color PointLight::calculateColor(const Scene &scene, const Ray &ray, float distance, const Vector &normal, MaterialPointer material) const {
  Vector point = ray.getPointAt(distance);

  Color ambientComponent;
  Color diffuseComponent;
  Color specularComponent;

  ambientComponent = componentwiseProduct(material->ambientColor, mAmbientIntensity);
  Color result = ambientComponent;

  Vector shadowRayDirection = mPosition - point;
  float	distanceToLight	= shadowRayDirection.length();
  float	attenuation	= 1 / (mConstantAttenutaionCoefficient + mLinearAttenutaionCoefficient * distanceToLight + mQuadraticAttenutaionCoefficient * distanceToLight * distanceToLight);
  result *= attenuation;

  shadowRayDirection.normalize(); 
  float	shadowRayDotNormal = shadowRayDirection.dotProduct(normal);

  // If the point is not illuminated
  if (shadowRayDotNormal <= 0.0) {
    return result;
  }

  Ray shadowRay(point + shadowRayDirection * EPS_FOR_SHADOW_RAYS, shadowRayDirection);	
  RayIntersection shadowRayIntersection = scene.calculateNearestIntersection(shadowRay);
  
  // If object is not in shadow
  if (!shadowRayIntersection.rayIntersectsWithShape || shadowRayIntersection.distanceFromRayOrigin > distanceToLight) {
    Color diffuseColor = material->diffuseColor;
    diffuseComponent  = componentwiseProduct(diffuseColor, mDiffuseIntensity * attenuation * shadowRayDotNormal);

    Vector lightReflect = shadowRayDirection - normal * 2 * shadowRayDirection.dotProduct(normal);
    lightReflect.normalize();

    Vector cameraDirection = ray.getOriginPosition() - point;
    cameraDirection.normalize();

    float	cosLightReflect = cameraDirection.dotProduct(lightReflect);
    if (cosLightReflect > 0.0) {
      Color specularColor = material->specularColor; 
      specularComponent	= componentwiseProduct(specularColor, mSpecularIntensity * powf(cosLightReflect, material->specularPower) * attenuation);
    }				
  }

  result += (diffuseComponent + specularComponent);
  return result;
}
Esempio n. 4
0
Vector Cone::getNormal(const Ray &ray, float distance) const {
  Vector coneAxis	= (mBottomCenter - mTop);
  coneAxis.normalize();
  Vector point = ray.getPointAt(distance);

  // If point is lying at bottom
  Vector pointPositionRelativelyToBottom	= point - mBottomCenter;
  if (fabs(coneAxis.dotProduct(pointPositionRelativelyToBottom)) < FLOAT_ZERO && 
      pointPositionRelativelyToBottom.dotProduct(pointPositionRelativelyToBottom) < mRadius * mRadius) {
    return coneAxis;
  }

  // Otherwise, if point is lying at side surface
  Vector approximatedNormal = point - (coneAxis * (point - mBottomCenter).dotProduct(coneAxis) + mBottomCenter);
  float radiansPerHeight = mRadius / (mBottomCenter - mTop).length();
  Vector normal = approximatedNormal + coneAxis * (-radiansPerHeight * approximatedNormal.length());
  normal.normalize();
  return normal;
}
Esempio n. 5
0
bool Sphere::intersectRay(const Ray &ray, Point &intersection) const {
    Vector3d centerToOrigin = ray.getOrigin() - center;
    // a = 0, т.к. нормируем вектор направления луча.
    double b = (Vector3d::dotProduct(ray.getDirection().normalize(), centerToOrigin));
    double c = centerToOrigin.lengthSquared() - radiusSquared;
    double d = b * b - c;
    if (d >= 0) {
        double sqrtOfD = sqrt(d);
        double t1 = -b + sqrtOfD;
        double t2 = -b - sqrtOfD;
        double t_min = std::min(t1, t2);
        double t_max = std::max(t1, t2);
        double t_closest = (t_min >= 0) ? t_min : t_max;
        if (t_closest > 0) {
            intersection = ray.getPointAt(t_closest);
            return true;
        } else {
            return false;
        }
    }
    return false;
}
Esempio n. 6
0
Vector Sphere::getNormal(const Ray &ray, float distance) const {
  Vector normal = (ray.getPointAt(distance) - mCenter) / mRadius;
  normal.normalize();
  return normal;
}
Esempio n. 7
0
RayIntersection Cone::intersectWithRay(const Ray &ray) const {
  Vector coneAxis	= (mBottomCenter - mTop);
  coneAxis.normalize();

  Vector rayOriginPosition = ray.getOriginPosition();
  Vector rayDirection = ray.getDirection();

  Vector bottomCenterToRayOrigin = rayOriginPosition - mTop;

  float rayDirectionDotAxis = rayDirection.dotProduct(coneAxis);
  float bottomCenterToRayOriginDotAxis = bottomCenterToRayOrigin.dotProduct(coneAxis);
  float radiansPerHeight = mRadius / (mBottomCenter - mTop).length();

  Vector u = rayDirection + coneAxis * (-rayDirectionDotAxis);
  Vector v = bottomCenterToRayOrigin + coneAxis * (-bottomCenterToRayOriginDotAxis);
  float  w = bottomCenterToRayOriginDotAxis * radiansPerHeight;

  float	radiansPerDirection = rayDirectionDotAxis * radiansPerHeight;


  // Solve square equation a * x^2 + b * x + c = 0
  float a = u.dotProduct(u) - radiansPerDirection * radiansPerDirection;
  float closestRoot = -1.f;
  float rayExit = -1.f;
  float root		= 0.f;
  std::vector<float> intersectionDistances;
  
  if (fabs(a) > FLOAT_ZERO) {
    float b = 2 * (u.dotProduct(v) - w * radiansPerDirection);
    float c = v.dotProduct(v) - w * w;
    float discriminant = b * b - 4 * a * c;

    if (discriminant < 0.0) {
      return RayIntersection();
    }

    discriminant = sqrtf(discriminant);
    float denominator = 1.0 / (2.0 * a);

    root = (-b - discriminant) * denominator;
    if (root > 0.0) {
      Vector point = ray.getPointAt(root);
      Vector bottomCenterToPoint = point - mTop;
      Vector topToPoint = point - mBottomCenter;
      if (coneAxis.dotProduct(bottomCenterToPoint) > 0.0 && (-coneAxis).dotProduct(topToPoint) > 0.0) {
        intersectionDistances.push_back(root);
        closestRoot = root;
      }
    }
    
    root = (-b + discriminant) * denominator;
    if (root > 0.0) {
      Vector point = ray.getPointAt(root);
      Vector bottomCenterToPoint = point - mTop;
      Vector topToPoint = point - mBottomCenter;
      if (coneAxis.dotProduct(bottomCenterToPoint) > 0.0 && (-coneAxis).dotProduct(topToPoint) > 0.0) {
        intersectionDistances.push_back(root);
        if (closestRoot < 0.0) {
          closestRoot = root;
        } else if (root < closestRoot) {
          rayExit = closestRoot;
          closestRoot = root;
        } else {
          rayExit = root;
        }
      }
    }
  }

  // Intersection with bottom
  if (fabs(rayDirectionDotAxis) < FLOAT_ZERO) {
    if (closestRoot > 0.0) {
      if (rayExit < 0.f) {
        intersectionDistances.insert(intersectionDistances.begin(), 0.f);
      }
      ConePointer pointer = ConePointer(new Cone(*this));
      return RayIntersection(true, pointer, closestRoot, getNormal(ray, closestRoot), intersectionDistances);
    }

    return RayIntersection();
  }

  // Intersection with top and bottom points
  root = (-coneAxis).dotProduct(rayOriginPosition - mBottomCenter) / rayDirectionDotAxis;
  if (root > 0.0)
  {
    Vector topToPoint = ray.getPointAt(root) - mBottomCenter;
    if (topToPoint.dotProduct(topToPoint) < mRadius * mRadius)
    {
      intersectionDistances.push_back(root);
      if (closestRoot < 0.0) {
        closestRoot = root;
        rayExit = root;
      } else if (root < closestRoot) {
        rayExit = closestRoot;
        closestRoot = root;
      } else {
        rayExit = root;
      }
    }
  }

  if (closestRoot > 0.0) {
    if (rayExit < 0.0) {
      intersectionDistances.insert(intersectionDistances.begin(), 0.f);
    }
    ConePointer pointer = ConePointer(new Cone(*this));
    return RayIntersection(true, pointer, closestRoot, getNormal(ray, closestRoot), intersectionDistances);
  }

  return RayIntersection();  
}
RGB SubsurfacePathtracer::trace(Ray p_ray, Vector3d cameraPos, int p_depth) {

	RGB radiance(0,0,0);
	RGB localRadiance(0,0,0);
	RayIntersection nearestRayInt;
	p_depth++;
	
	bool intersected = false;

	if(scene->kdTree == NULL) {
		intersected = p_ray.nearestIntersection(scene->getObjects(), scene->getObjectCount(), &nearestRayInt);
	} else {
		intersected = scene->kdTree->nearestIntersection(&p_ray, &nearestRayInt);
	}

	if(intersected) {
		if(!(nearestRayInt.object->getShader()->isLight() && p_ray.getDiffuse())) {
			//local ilumination:
			Vector3d viewVec = cameraPos - nearestRayInt.point;
			viewVec.normalize();
			localRadiance = nearestRayInt.object->getShader()->getDiffuseRadiance(nearestRayInt.object, nearestRayInt.point, nearestRayInt.normal, nearestRayInt.uv, viewVec, scene);

			radiance = localRadiance;

			if(nearestRayInt.object->getShader()->hasSubsurface()) {
				radiance = radiance + subsurface(&nearestRayInt, &p_ray);
				//return subsurface(&nearestRayInt, &p_ray);
			}

			int outVecsCount = 0;
			RGB indirectRadiance;

			if(p_depth == 1) {
				for(int i = 0; i < 5; i++) {
					if(p_depth < maxDepth) {
						Ray outRays[10];
						RGB values[10];
						outVecsCount = nearestRayInt.object->getShader()->getBRDFSampledRays(nearestRayInt.object, nearestRayInt.point, nearestRayInt.normal, nearestRayInt.uv, viewVec, p_ray.getDir(), outRays, values);
						
						for(int s = 0; s < outVecsCount; s++) {
							Ray ray = outRays[s];
							indirectRadiance = indirectRadiance + (trace(ray, cameraPos, p_depth) * values[s]) ;
						}
					}

					indirectRadiance;
				}

				indirectRadiance = indirectRadiance / 5;
			} else {
				if(p_depth < maxDepth) {
					Ray outRays[10];
					RGB values[10];
					outVecsCount = nearestRayInt.object->getShader()->getBRDFSampledRays(nearestRayInt.object, nearestRayInt.point, nearestRayInt.normal, nearestRayInt.uv, viewVec, p_ray.getDir(), outRays, values);
					
					for(int s = 0; s < outVecsCount; s++) {
						Ray ray = outRays[s];
						indirectRadiance = indirectRadiance + (trace(ray, cameraPos, p_depth) * values[s]) ;
					}
				}	
			}

			if(outVecsCount > 0) {
				radiance =  radiance + indirectRadiance;
			}

		}
	} else if(scene->getBackground() != NULL) {
		radiance = scene->getBackground()->getRadianceAt(p_ray.getPoint(), p_ray.getPointAt(FAR_AWAY));
	}

	return radiance;
}
Color RayTracer::traceRay(const Ray &ray, int currentRecursionDepth, bool isRayReflected,
                          float environmentDensity, float reflectionIntensity, 
                          RayIntersection &intersection) {
  if (currentRecursionDepth > MAX_TRACER_RECURSION_DEPTH) {
    return Color();
  }

  intersection = mScene->calculateNearestIntersection(ray);
  
  if (!intersection.rayIntersectsWithShape) {
    if (isRayReflected) {
      return Color();
    }
    return mScene->getBackgroundMaterial()->ambientColor;
  }

  Vector intersectionPoint = ray.getPointAt(intersection.distanceFromRayOrigin);
  ShapePointer shape = intersection.shape;
  MaterialPointer shapeMaterial = shape->getMaterial();
  Vector normal = intersection.normalAtInresectionPoint;

  Color pixelColor = mScene->calculateIlluminationColor(ray, intersection.distanceFromRayOrigin, normal, shapeMaterial);

  /* Process reflection and refraction */

  Vector rayDirection = ray.getDirection();
  float viewProjection = rayDirection.dotProduct(normal);
  // Turn normal to the front side
  Vector outNormal = normal;
  if (viewProjection > 0.0) {
    outNormal = -normal;
  }

  // Calculate fresnel factor
  bool isTotalInternalReflection = false;
  float fresnel = calculateFrenselCoefficient(rayDirection, environmentDensity, shapeMaterial->densityFactor, outNormal, isTotalInternalReflection);

  // Calculate reflection
  if (shapeMaterial->reflectionFactor > 0.0 && reflectionIntensity > EPS_FOR_REFLECTION_RAYS) {
    // Reflect ray	
    Vector reflectedRayDirection = rayDirection - outNormal * 2.0 * rayDirection.dotProduct(outNormal);
    RayIntersection reflectedRayIntersection;
    Color reflectedColor = traceRay(Ray(intersectionPoint + reflectedRayDirection * EPS_FOR_REFLECTION_RAYS, reflectedRayDirection), 
                                     currentRecursionDepth + 1,
                                     true,
                                     shapeMaterial->densityFactor,
                                     reflectionIntensity * shapeMaterial->reflectionFactor,      
                                     reflectedRayIntersection);
    reflectedColor *=  reflectionIntensity * shapeMaterial->reflectionFactor * fresnel;
    pixelColor += componentwiseProduct(reflectedColor, shapeMaterial->diffuseColor);
  }

  // Calculate refraction
  if (shapeMaterial->refractionFactor > 0.0) {
    float shapeDensity	= shapeMaterial->densityFactor;
    Vector reflectedRayDirection = claculateRefractedRayDirection(rayDirection, outNormal, environmentDensity, shapeDensity, isTotalInternalReflection);
    if (!isTotalInternalReflection) {
      RayIntersection	refractedRayIntersection;
      Color refracted  = traceRay(Ray(intersectionPoint + reflectedRayDirection * EPS_FOR_REFLECTION_RAYS, reflectedRayDirection), 
                                  currentRecursionDepth + 1,
                                  true,
                                  shapeDensity, 
                                  reflectionIntensity,         
                                  refractedRayIntersection);
      // Use Burger-Lambert-Beer law
      if (refractedRayIntersection.rayIntersectsWithShape) {
        Color absorbance   = (shapeMaterial->diffuseColor) * 0.15f * (-refractedRayIntersection.distanceFromRayOrigin);
        Color transparency = Color(expf(absorbance.r), expf(absorbance.g), expf(absorbance.b));
        pixelColor += componentwiseProduct(refracted,  transparency) * (1.0 - fresnel);
      }
    }
  }

  return pixelColor;
}