Ejemplo n.º 1
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.º 2
0
bool Raytracer::isInShadow(const SurfaceSample& intersector, const Vector3 w_i, const float lightDistance) const
{
	bool returnValue = false;

	if (_settings._shadowCast)
	{
		// Check if in Shadow, cast ray backwards, up to distance to light....
		Ray rayToLight(intersector.shadingLocation + (intersector.shadingNormal * 0.0001f), (w_i.unit()));
		Tri::Intersector shadowIntersector;
		float shadowDistance = lightDistance;
		if (_triTree.intersectRay(rayToLight, shadowIntersector, shadowDistance))
		{
			returnValue = true;
		}
	}

	return returnValue;
}
Ejemplo n.º 3
0
void shade(const Scene * scene, const int level, const C_FLT weight,
           const Ray &ray, Intercept * intercepts, Color * color) {
  Material * entryMat = intercepts[0].material,
           * hitMat = intercepts[0].enter?
                      intercepts[0].primitive->material: ray.medium;

  C_FLT specWeight = hitMat->specular.magnitude() * weight,
        transWeight = hitMat->transmission.magnitude() * weight;

  Vector3D specDir, transDir, normal;
  std::vector<P_FLT> mapping;

  Point3D interceptPoint = ray.rayPoint(intercepts[0].t);

  intercepts[0].primitive->getIntersect(interceptPoint, &normal, &mapping);
  if (dotProduct(ray.dir, normal) > 0.0f) {
    normal.negate();
  }
  specularDirection(ray.dir, normal, &specDir);
  bool transmission = transmissionDirection(entryMat, hitMat, ray.dir, normal,
                                            &transDir);

  *color += scene->ambience * hitMat->ambience;

  for (std::vector<Light *>::const_iterator itr = scene->lights.begin();
       itr != scene->lights.end(); itr++) {
    Vector3D pointToLight = (*itr)->orig - interceptPoint;
    P_FLT distanceToLight = pointToLight.normalize();
    Ray rayToLight(interceptPoint, pointToLight, NULL);

    P_FLT lightDotNormal = dotProduct(pointToLight, normal);
    if (fGreaterZero(lightDotNormal) &&
        fGreaterZero(shadow(scene, rayToLight, distanceToLight))) {
      // Light source diffuse reflection
      *color += (*itr)->color * hitMat->diffuse * lightDotNormal;

      // Light source specular reflection
      Vector3D h = pointToLight - ray.dir;
      h.normalize();
      P_FLT specDot = dotProduct(normal, h);
      if (specDot > 0.0f) {
        *color += (*itr)->color * hitMat->specular *
                  pow(specDot, hitMat->shine);
      }
    } else if (transmission && fLessZero(lightDotNormal) &&
               fLessZero(shadow(scene, rayToLight, distanceToLight))) {
      // Light source specular transmission
      C_FLT refrRatio = hitMat->refraction / entryMat->refraction;
      if (!fEqual(refrRatio, 1.0f)) {
        Vector3D h_j = (-ray.dir - pointToLight * refrRatio) /
                       (refrRatio - 1);
        h_j.normalize();

        // TODO(kent): Define transmission highlight coefficient
        *color += (*itr)->color * hitMat->transmission *
                  pow(dotProduct(-normal, h_j), hitMat->shine);
      }
    }
  }

  if (level < MAX_LEVEL) {
    // Other body specular reflection
    if (specWeight > MIN_WEIGHT) {
      Ray specRay(interceptPoint, specDir, entryMat);
      Color specColor;

      trace(scene, level + 1, specWeight, specRay, &specColor);
      *color += specColor * hitMat->specular;
    }

    // Other body specular transmission
    if (transWeight > MIN_WEIGHT) {
      if (transmission) {
        Ray transRay(interceptPoint, transDir, hitMat);
        Color transColor;

        trace(scene, level + 1, transWeight, transRay, &transColor);
        *color += transColor * hitMat->transmission;
      } else {
        // TODO(kent): Handle total internal reflection
      }
    }
  }

  if (intercepts[0].enter && intercepts[0].primitive->texture != NULL) {
    *color *= intercepts[0].primitive->getTexColor(mapping);
  }
}
Ejemplo n.º 4
0
Eigen::Vector4d getColor(const Ray &ray, unsigned int recursionLevel, unsigned int transDepth,
                         std::array<int, MAX_DEPTH + 1> &objStack) {
    BOOST_ASSERT_MSG(std::abs(1 - ray.dir.norm()) < EPSILON, "Got ray with non-unit direction");
    const intersection_t isect = getIntersection(ray);
    int objId;
    if ((objId = isect.objId) < 0) return Eigen::Vector4d::Zero();

    auto &objects = scene.getObjects();
    auto &lights = scene.getLights();
    Eigen::Vector4d I = Eigen::Vector4d::Zero();

    Eigen::Vector4d pointOfIntersection = ray.origin + isect.dist * ray.dir;

    Eigen::Vector4d N = objects[objId]->getUnitNormal(pointOfIntersection);
    Eigen::Vector4d V = -1 * ray.dir;

    auto mat = scene.getMaterial(objects[objId]->matId);

    for (unsigned int i = 0 ; i < lights.size(); ++i) {
        if (lights[i]->isAmbient()) {
            I += mat.Ka * lights[i]->getAmountOfLight(pointOfIntersection).cwiseProduct(mat.rgb);
            continue;
        }
        Eigen::Vector4d L = lights[i]->getVectorToLight(pointOfIntersection);
        Ray rayToLight(pointOfIntersection, L, objId);

        bool lightVisible = true;
        if (lights[i]->getShadowOn()) {
            double distToBlockingObject = getIntersection(rayToLight).dist;
            double distToLight = (pointOfIntersection - lights[i]->getPosition()).norm();

            lightVisible = distToBlockingObject <= EPSILON ||
                distToBlockingObject >= distToLight;
        }
        if (lightVisible) {
            /* Diffuse Reflection */
            Eigen::Vector4d Il = lights[i]->getAmountOfLight(pointOfIntersection);
            // Amount of light visible on surface determined by angle to light source
            double lambertCos = L.dot(N);
            if (lambertCos > 0) {
                I += mat.Kd * lambertCos * mat.rgb.cwiseProduct(Il);
            } else {
                continue;
            }

            /* Specular Reflection */
            Eigen::Vector4d reflection = 2 * N.dot(rayToLight.dir) * N - rayToLight.dir;
            double specCoeff = reflection.dot(V);
            if (specCoeff > 0) {
                specCoeff = std::max(0.0, pow(specCoeff, mat.ns));
                I += specCoeff * mat.Ks * mat.rgb.cwiseProduct(Il);
            }
        }
    }

    if (recursionLevel < MAX_DEPTH) {
        // Work out where in material stack we are
        int nextTransDepth;
        int nextObjId;
        if (objStack[transDepth] == objId) {
            nextTransDepth = transDepth - 1;
            nextObjId = objStack[transDepth - 1];
        } else {
            nextTransDepth = transDepth + 1;
            objStack[nextTransDepth] = objId;
            nextObjId = objId;
        }

        // Compute intensity of reflected ray, if necessary
        if (reflect && mat.Kr > 0)	{
            Ray reflectionRay(pointOfIntersection,  ray.dir - (2 * N.dot(ray.dir)) * N, nextObjId);
            I += mat.Kr * getColor(reflectionRay, recursionLevel + 1, nextTransDepth, objStack);
        }

        // Compute intensity of transmission ray, if necessary
        if (refract && mat.Kt > 0) {
            const double etaIncident = (objStack[transDepth] == ID_AIR) ? 1.0 :
                scene.getMaterial(objects[objStack[transDepth]]->matId).Irefract;
            double cosThetaI, etaRefract;
            if (objStack[transDepth] == objId) { // Exiting a material
                cosThetaI = ray.dir.dot(N);
                etaRefract = (objStack[transDepth - 1] == ID_AIR) ? 1.0 :
                    scene.getMaterial(objects[objStack[transDepth - 1]]->matId).Irefract;
            } else {
                cosThetaI = V.dot(N);
                etaRefract = scene.getMaterial(objects[objId]->matId).Irefract;
            }
            const double n = etaIncident/etaRefract;
            const double cosThetaR = sqrt(1 - (n * n) * (1 - cosThetaI * cosThetaI));
            Ray T(pointOfIntersection, (n * ray.dir - (cosThetaR - n * cosThetaI) * N).normalized(), nextObjId);
            I += mat.Kt * getColor(T, recursionLevel + 1, nextTransDepth, objStack);
        }
    }

    return I;

}