예제 #1
0
Vector3D Ray::Trace(Environment &env, int recursion) {
	if(recursion > MAX_RECURSION) return BACKGROUND_COLOR;
	Intersection inter = FindClosestIntersection(env);
	if(inter.obj == NULL)
		return BACKGROUND_COLOR;

	Vector3D position = source + direction * inter.dist,
			 normal = inter.obj->Normal(position);

	if(normal * direction > 0) normal = -normal;

	Vector3D reflect_direction = direction - 2 *(normal * direction) * normal;
	Vector3D half_reflect = (direction + normal).Normalize();
	Ray reflected_ray = Ray(position, reflect_direction);

	Vector3D object_color = inter.obj->GetColorAt(position),
			 ambient_color = env.ambient_light->Color(),
			 diffuse_color = LightTrace(position, normal, env, recursion),
			 specular_color = reflected_ray.Trace(env, recursion + 1),
			 refraction_color = Refract(inter, env, recursion);

	Vector3D total_color =
			ambient_color * inter.obj->surface().ambiente +
			diffuse_color * inter.obj->surface().difusao;

	total_color = combine_colors(total_color, object_color);
	total_color = total_color
			+ specular_color * inter.obj->surface().especular
				* pow(std::max(0.0, normal * half_reflect), inter.obj->surface().brilho)
			+ refraction_color * inter.obj->surface().transmissao;

	return clamp_color(total_color);
}
예제 #2
0
Spectrum FresnelSpecular::Sample_f(const Vector3f &wo, Vector3f *wi,
                                   const Point2f &u, Float *pdf,
                                   BxDFType *sampledType) const {
    Float F = FrDielectric(CosTheta(wo), etaA, etaB);
    if (u[0] < F) {
        // Compute specular reflection for _FresnelSpecular_

        // Compute perfect specular reflection direction
        *wi = Vector3f(-wo.x, -wo.y, wo.z);
        if (sampledType)
            *sampledType = BxDFType(BSDF_SPECULAR | BSDF_REFLECTION);
        *pdf = F;
        return F * R / AbsCosTheta(*wi);
    } else {
        // Compute specular transmission for _FresnelSpecular_

        // Figure out which $\eta$ is incident and which is transmitted
        bool entering = CosTheta(wo) > 0;
        Float etaI = entering ? etaA : etaB;
        Float etaT = entering ? etaB : etaA;

        // Compute ray direction for specular transmission
        if (!Refract(wo, Faceforward(Normal3f(0, 0, 1), wo), etaI / etaT, wi))
            return 0;
        Spectrum ft = T * (1 - F);

        // Account for non-symmetry with transmission to different medium
        if (mode == TransportMode::Radiance)
            ft *= (etaI * etaI) / (etaT * etaT);
        if (sampledType)
            *sampledType = BxDFType(BSDF_SPECULAR | BSDF_TRANSMISSION);
        *pdf = 1 - F;
        return ft / AbsCosTheta(*wi);
    }
}
예제 #3
0
void RealisticCamera::DrawRayPathFromScene(const Ray &r, bool arrow,
                                           bool toOpticalIntercept) const {
    Float elementZ = LensFrontZ() * -1;

    // Transform _ray_ from camera to lens system space
    static const Transform CameraToLens = Scale(1, 1, -1);
    Ray ray = CameraToLens(r);
    for (size_t i = 0; i < elementInterfaces.size(); ++i) {
        const LensElementInterface &element = elementInterfaces[i];
        bool isStop = (element.curvatureRadius == 0);
        // Compute intersection of ray with lens element
        Float t;
        Normal3f n;
        if (isStop)
            t = -(ray.o.z - elementZ) / ray.d.z;
        else {
            Float radius = element.curvatureRadius;
            Float zCenter = elementZ + element.curvatureRadius;
            if (!IntersectSphericalElement(radius, zCenter, ray, &t, &n))
                return;
        }
        Assert(t >= 0.f);

        printf("Line[{{%f, %f}, {%f, %f}}],", ray.o.z, ray.o.x, ray(t).z,
               ray(t).x);

        // Test intersection point against element aperture
        Point3f pHit = ray(t);
        Float r2 = pHit.x * pHit.x + pHit.y * pHit.y;
        Float apertureRadius2 = element.apertureRadius * element.apertureRadius;
        if (r2 > apertureRadius2) return;
        ray.o = pHit;

        // Update ray path for from-scene element interface interaction
        if (!isStop) {
            Vector3f wt;
            Float etaI = (i == 0 || elementInterfaces[i - 1].eta == 0.f)
                             ? 1.f
                             : elementInterfaces[i - 1].eta;
            Float etaT = (elementInterfaces[i].eta != 0.f)
                             ? elementInterfaces[i].eta
                             : 1.f;
            if (!Refract(Normalize(-ray.d), n, etaI / etaT, &wt)) return;
            ray.d = wt;
        }
        elementZ += element.thickness;
    }

    // go to the film plane by default
    {
        Float ta = -ray.o.z / ray.d.z;
        if (toOpticalIntercept) {
          ta = -ray.o.x / ray.d.x;
          printf("Point[{%f, %f}], ", ray(ta).z, ray(ta).x);
        }
        printf("%s[{{%f, %f}, {%f, %f}}]", arrow ? "Arrow" : "Line", ray.o.z,
               ray.o.x, ray(ta).z, ray(ta).x);
    }
}
예제 #4
0
Spectrum MicrofacetTransmission::Sample_f(const Vector3f &wo, Vector3f *wi,
                                          const Point2f &u, Float *pdf,
                                          BxDFType *sampledType) const {
    Vector3f wh = distribution->Sample_wh(wo, u);
    Float eta = CosTheta(wo) > 0 ? (etaA / etaB) : (etaB / etaA);
    if (!Refract(wo, (Normal3f)wh, eta, wi)) return 0;
    *pdf = Pdf(wo, *wi);
    return f(wo, *wi);
}
예제 #5
0
Point3D RayScene::GetColor(Ray3D ray,int rDepth,Point3D cLimit){
	if (rDepth == 0) {return Point3D();}
	if (cLimit[0] > 1 && cLimit[1] > 1 && cLimit[2] > 1) {return Point3D();}

	RayIntersectionInfo iInfo;
	double resp = group->intersect(ray, iInfo, -1);
	if (resp > 0) {

		//Calculating reflection values.
		Point3D reflectedDirection = Reflect(ray.direction, iInfo.normal);
		Ray3D reflectedRay(iInfo.iCoordinate+(reflectedDirection.unit()*0.0001), reflectedDirection.unit());
		//Calculating and finding the refraction values.
		Point3D refractedDirection;
		double refIndex;
		if (ray.direction.dot(iInfo.normal) < 0) {
			refIndex = iInfo.material->refind;
		} else {
			refIndex = 1/iInfo.material->refind;
		}
		int refract = Refract(ray.direction.unit(), iInfo.normal.unit(), refIndex, refractedDirection);
		Ray3D refractedRay(iInfo.iCoordinate+(refractedDirection.unit()*0.0001), refractedDirection.unit());
		Point3D refractedTransparency = iInfo.material->transparent;

		//Calculating light contributions to the point.
		Point3D diffuse = Point3D(0,0,0);
		Point3D specular = Point3D(0,0,0);
		for (int i=0; i<lightNum; i++) {
			RayIntersectionInfo iInfo2 = iInfo;
			int iSectCount = 0;
			Point3D diffuseResp = lights[i]->getDiffuse(camera->position, iInfo2);
			Point3D specularResp = lights[i]->getSpecular(camera->position, iInfo2);
			Point3D transparency = lights[i]->transparency(iInfo2, group, cLimit);
			diffuse += diffuseResp*transparency;
			specular += specularResp*transparency;
		}
		Point3D response = iInfo.material->ambient*ambient+iInfo.material->emissive + diffuse + specular
		 					+ GetColor(reflectedRay, rDepth-1, cLimit/iInfo.material->specular)
							+ GetColor(refractedRay, rDepth-1, cLimit/iInfo.material->specular)*refractedTransparency;

		for (int i = 0; i <3; i++) {
			if (response[i] < 0) {
				response[i] = 0;
			}
			if (response[i] > 1) {
				response[i] = 1;
			}
		}
		return response;
	}
	else if (ray.position[0]==camera->position[0] && ray.position[1]==camera->position[1] && ray.position[2]==camera->position[2]) {
		return background;
	} else return Point3D();
}
예제 #6
0
bool RealisticCamera::TraceLensesFromScene(const Ray &rCamera,
        Ray *rOut) const {
    Float elementZ = -LensFrontZ();
    // Transform _rCamera_ from camera to lens system space
    static const Transform CameraToLens = Scale(1, 1, -1);
    Ray rLens = CameraToLens(rCamera);
    for (size_t i = 0; i < elementInterfaces.size(); ++i) {
        const LensElementInterface &element = elementInterfaces[i];
        // Compute intersection of ray with lens element
        Float t;
        Normal3f n;
        bool isStop = (element.curvatureRadius == 0);
        if (isStop)
            t = (elementZ - rLens.o.z) / rLens.d.z;
        else {
            Float radius = element.curvatureRadius;
            Float zCenter = elementZ + element.curvatureRadius;
            if (!IntersectSphericalElement(radius, zCenter, rLens, &t, &n))
                return false;
        }
        Assert(t >= 0);

        // Test intersection point against element aperture
        Point3f pHit = rLens(t);
        Float r2 = pHit.x * pHit.x + pHit.y * pHit.y;
        if (r2 > element.apertureRadius * element.apertureRadius) return false;
        rLens.o = pHit;

        // Update ray path for from-scene element interface interaction
        if (!isStop) {
            Vector3f wt;
            Float etaI = (i == 0 || elementInterfaces[i - 1].eta == 0)
                         ? 1
                         : elementInterfaces[i - 1].eta;
            Float etaT =
                (elementInterfaces[i].eta != 0) ? elementInterfaces[i].eta : 1;
            if (!Refract(Normalize(-rLens.d), n, etaI / etaT, &wt))
                return false;
            rLens.d = wt;
        }
        elementZ += element.thickness;
    }
    // Transform _rLens_ from lens system space back to camera space
    if (rOut != nullptr) {
        static const Transform LensToCamera = Scale(1, 1, -1);
        *rOut = LensToCamera(rLens);
    }
    return true;
}
bool DielectricMaterial::Scatter( const Ray& ray, const HitRecord& record, Vector3& attenuation, Ray& scattered ) const
{
	attenuation = Vector3( 1.f, 1.f, 1.f );
	const float dirDotNormal = ray.Direction().Dot( record.normal );

	Vector3 outwardNormal;
	float niOverNt;
	float cosine;
	
	if ( dirDotNormal > 0.f )
	{
		outwardNormal = -record.normal;
		niOverNt = refractionIndex;
		//cosine = refractionIndex * dirDotNormal / ray.Direction().Length();
		cosine = dirDotNormal / ray.Direction().Length();
		cosine = std::sqrt( 1.f - refractionIndex * refractionIndex * ( 1.f - cosine * cosine ) );
	}
	else
	{
		outwardNormal = record.normal;
		niOverNt = 1.f / refractionIndex;
		cosine = -dirDotNormal / ray.Direction().Length();
	}

	const Vector3 reflected = Reflect( ray.Direction(), record.normal );

	float reflectProbability;
	Vector3 refracted;
	if ( Refract( ray.Direction(), outwardNormal, niOverNt, refracted ) )
	{
		reflectProbability = Schlick( cosine, refractionIndex );
	}
	else
	{
		reflectProbability = 1.f;
	}

	if ( Rand01() < reflectProbability )
	{
		scattered = Ray( record.point, reflected );
	}
	else
	{
		scattered = Ray( record.point, refracted );
	}

	return true;
}
예제 #8
0
Spectrum SpecularTransmission::Sample_f(const Vector3f &wo, Vector3f *wi,
                                        const Point2f &sample, Float *pdf,
                                        BxDFType *sampledType) const {
    // Figure out which $\eta$ is incident and which is transmitted
    bool entering = CosTheta(wo) > 0;
    Float etaI = entering ? etaA : etaB;
    Float etaT = entering ? etaB : etaA;

    // Compute ray direction for specular transmission
    if (!Refract(wo, Faceforward(Normal3f(0, 0, 1), wo), etaI / etaT, wi))
        return 0;
    *pdf = 1;
    Spectrum ft = T * (Spectrum(1.) - fresnel.Evaluate(CosTheta(*wi)));
    // Account for non-symmetry with transmission to different medium
    if (mode == TransportMode::Radiance) ft *= (etaI * etaI) / (etaT * etaT);
    return ft / AbsCosTheta(*wi);
}
예제 #9
0
/**********
 * DESCRIPTION:   calculate pixel color
 * INPUT:         x        x position
 *                y        y position
 *                normal   surface normal
 * OUTPUT:        -
 **********/
void PREVIEW::CalcPixel(int x, int y, VECTOR *normal)
{
	PREVIEW_TEXTURE *ptexture;
	float costheta;
	float cosalpha,intens;
	VECTOR refl, newdir, norm, pos;
	float t;
	COLOR color, map;
	float x1,y1;

	norm = *normal;
	pos = norm;

	ptexture = texture_root;
	while(ptexture)
	{
		ptexture->Work(this, &pos, &norm);
		ptexture = (PREVIEW_TEXTURE*)ptexture->GetNext();
	}

	color.r = ambient.r * global.ambient.r;
	color.g = ambient.g * global.ambient.g;
	color.b = ambient.b * global.ambient.b;

	if(surf->flags & SURF_BRIGHT)
	{
		color.r += diffuse.r;
		color.g += diffuse.g;
		color.b += diffuse.b;
	}
	else
	{
		t = -2.f*norm.z;
		refl.x = t*norm.x;
		refl.y = t*norm.y;
		refl.z = 1.f + t*norm.z;

		costheta = -dotp(&norm, &light);
		if(costheta <= 0.f)
		{
			/* Light source is on opposite side of surface, hence light must be
			 * transmitted through ... */
			if(translucency > EPSILON)
			{
				color.r += -costheta * difftrans.r;
				color.g += -costheta * difftrans.g;
				color.b += -costheta * difftrans.b;
				if(transphong > EPSILON)
				{
					/* calculate reflected ray direction */
					cosalpha = -dotp(&refl, &light);
					if(cosalpha > EPSILON)
					{
						/* Specular highlight = cosine of the angle raised to the
						 * appropriate power */
						intens = pow(cosalpha, transphong) * translucency;
						color.r += intens * spectrans.r;
						color.g += intens * spectrans.g;
						color.b += intens * spectrans.b;
					}
				}
			}
		}
		else
		{
			if(costheta > EPSILON)
			{
				color.r += costheta * diffuse.r;
				color.g += costheta * diffuse.g;
				color.b += costheta * diffuse.b;
			}
			if(refphong > EPSILON)
			{
				/* calculate reflected ray direction */
				cosalpha = -dotp(&refl, &light);
				if(cosalpha > EPSILON)
				{
					intens = pow(cosalpha, refphong);
					color.r += intens * specular.r;
					color.g += intens * specular.g;
					color.b += intens * specular.b;
				}
			}
		}

		if(transpar.r > EPSILON ||
			transpar.g > EPSILON ||
			transpar.b > EPSILON)
		{
			if(!Refract(&newdir, 1.f/refrindex, &norm, norm.z))
			{
				color.r = color.r * (1.-transpar.r);
				color.g = color.g * (1.-transpar.g);
				color.b = color.b * (1.-transpar.b);

				t = (pos.z + .5f) / newdir.z;
				x1 = (pos.x + newdir.x * t) * 4.f;
				y1 = (pos.y + newdir.y * t) * 4.f;

				if(x1 < 0.f)
					x1 -= 1.f;
				if(y1 < 0.f)
					y1 -= 1.f;
				if(((int)x1 + (int)y1) & 1)
				{
					color.r += transpar.r;
					color.g += transpar.g;
					color.b += transpar.b;
				}
			}
		}

		if(reflect.r > EPSILON ||
			reflect.g > EPSILON ||
			reflect.b > EPSILON)
		{
			ApplyReflMap(&norm, &map);
			color.r += reflect.r * map.r;
			color.g += reflect.g * map.g;
			color.b += reflect.b * map.b;
		}
	}

	if(texture_root)
	{
		ambient = surf->ambient;
		diffuse = surf->diffuse;
		specular = surf->specular;
		reflect = surf->reflect;
		transpar = surf->transpar;
		difftrans = surf->difftrans;
		spectrans = surf->spectrans;
		refphong = refphong;
		transphong = transphong;
		foglength = foglength;
		refrindex = refrindex;
		translucency = translucency;
	}

	if(color.r > 1.f)
	{
		t = 1.f/color.r;
		color.r = 1.f;
		color.g *= t;
		color.b *= t;
	}
	if(color.g > 1.f)
	{
		t = 1.f/color.g;
		color.r *= t;
		color.g = 1.f;
		color.b *= t;
	}
	if(color.b > 1.f)
	{
		t = 1.f/color.b;
		color.r *= t;
		color.g *= t;
		color.b = 1.f;
	}
	line[x + y*xres].r = (UBYTE)(color.r*255.f);
	line[x + y*xres].g = (UBYTE)(color.g*255.f);
	line[x + y*xres].b = (UBYTE)(color.b*255.f);
}
예제 #10
0
void RealisticCamera::DrawRayPathFromFilm(const Ray &r, bool arrow,
        bool toOpticalIntercept) const {
    Float elementZ = 0;
    // Transform _ray_ from camera to lens system space
    static const Transform CameraToLens = Scale(1, 1, -1);
    Ray ray = CameraToLens(r);
    printf("{ ");
    if (!TraceLensesFromFilm(r, nullptr)) printf("Dashed, ");
    for (int i = elementInterfaces.size() - 1; i >= 0; --i) {
        const LensElementInterface &element = elementInterfaces[i];
        elementZ -= element.thickness;
        bool isStop = (element.curvatureRadius == 0);
        // Compute intersection of ray with lens element
        Float t;
        Normal3f n;
        if (isStop)
            t = -(ray.o.z - elementZ) / ray.d.z;
        else {
            Float radius = element.curvatureRadius;
            Float zCenter = elementZ + element.curvatureRadius;
            if (!IntersectSphericalElement(radius, zCenter, ray, &t, &n))
                goto done;
        }
        Assert(t >= 0);

        printf("Line[{{%f, %f}, {%f, %f}}],", ray.o.z, ray.o.x, ray(t).z,
               ray(t).x);

        // Test intersection point against element aperture
        Point3f pHit = ray(t);
        Float r2 = pHit.x * pHit.x + pHit.y * pHit.y;
        Float apertureRadius2 = element.apertureRadius * element.apertureRadius;
        if (r2 > apertureRadius2) goto done;
        ray.o = pHit;

        // Update ray path for element interface interaction
        if (!isStop) {
            Vector3f wt;
            Float etaI = element.eta;
            Float etaT = (i > 0 && elementInterfaces[i - 1].eta != 0)
                         ? elementInterfaces[i - 1].eta
                         : 1;
            if (!Refract(Normalize(-ray.d), n, etaI / etaT, &wt)) goto done;
            ray.d = wt;
        }
    }

    ray.d = Normalize(ray.d);
    {
        Float ta = std::abs(elementZ / 4);
        if (toOpticalIntercept) {
            ta = -ray.o.x / ray.d.x;
            printf("Point[{%f, %f}], ", ray(ta).z, ray(ta).x);
        }
        printf("%s[{{%f, %f}, {%f, %f}}]", arrow ? "Arrow" : "Line", ray.o.z,
               ray.o.x, ray(ta).z, ray(ta).x);

        // overdraw the optical axis if needed...
        if (toOpticalIntercept)
            printf(", Line[{{%f, 0}, {%f, 0}}]", ray.o.z, ray(ta).z * 1.05f);
    }

done:
    printf("}");
}
예제 #11
0
void Scene::BuildCornellBoxScene(std::vector<Shape*> &objects)
{
	camera = new Camera(
		Point(-260, 0, 90),
		Point(-199, 0, 90)
		);

	float lightEnergy = 35e8;

	lights.push_back(new SphereLight(Point(0, 0, 160), 3, Color(lightEnergy,lightEnergy,lightEnergy),1));

	Color walls(0.1f,0.1f,0.1f);
	Material* white = new Material(Ambient(0.3,0.3,0.3),Diffuse(0.9, 0.9, 0.9),walls);

	AddObject("files\\cornell_box\\cornell_box_floor.3ds", new Material(Color(0.3,0.3,0.3),Color(0.9,0.9,0.9),walls, Reflect(0.2, 0.2, 0.2)), objects);
	AddObject("files\\cornell_box\\cornell_box_ceil.3ds", white, objects);
	AddObject("files\\cornell_box\\cornell_box_right_wall.3ds", new Material(Color(0.,0.1,0.),Color(0.4,1,0.4),walls), objects);
	AddObject("files\\cornell_box\\cornell_box_back.3ds", white, objects);
	AddObject("files\\cornell_box\\cornell_box_left_wall.3ds", new Material(Color(0.1,0.,0.),Color(1,0.4,0.4),walls), objects);

	AddObject("files\\cornell_box\\cornell_box_box1.3ds", white, objects);
	AddObject("files\\cornell_box\\cornell_box_box2.3ds", white, objects);

	objects.push_back(new Sphere(Point(-35,-45,20),15,new Material(Ambient(0,0,0),Diffuse(0,0,0),Specular(0,0,0), Reflect(0,0,0), Refract(1,1,1), 1.51, 1), Shape::GetUniqueID()));
	objects.push_back(new Sphere(Point(-50,50,15),15,new Material(Ambient(0,0,0),Diffuse(0,0,0),Specular(0,0,0), Reflect(1,1,1)), Shape::GetUniqueID() ));
}