Пример #1
0
glm::vec3 Transparent::shade(const ShadeRec& sr)const
{
	glm::vec3 L(Phong::shade(sr));

	glm::vec3 incoming = -sr.ray.getDirection();
	glm::vec3 reflected;
	glm::vec3 fr = reflectiveBrdf->sampleF(sr,incoming,reflected);
	Ray reflectedRay(sr.hitPoint,reflected);

	if(specularBtfd->tir(sr))
	{
		//comment this out to remove the reflection and get cool effects
		L +=  sr.world.getTracer()->traceRay(reflectedRay,sr.depth + 1);
		//kr = 1.0
	}
	else
	{
		glm::vec3 transmitted;
		glm::vec3 ft = specularBtfd->sampleF(sr,incoming,transmitted);
		Ray transmittedRay(sr.hitPoint,transmitted);

		glm::vec3 reflectedColor = sr.world.getTracer()->traceRay(reflectedRay,sr.depth + 1) * fabs(glm::dot(sr.normal,reflected));
		fr.x *= reflectedColor.x;
		fr.y *= reflectedColor.y;
		fr.z *= reflectedColor.z;
		glm::vec3 transmittedColor = sr.world.getTracer()->traceRay(transmittedRay,sr.depth + 1) * fabs(glm::dot(sr.normal,transmitted));
		ft.x *= transmittedColor.x;
		ft.y *= transmittedColor.y;
		ft.z *= transmittedColor.z;
		L += fr + ft;
	}

	return L;
}
Пример #2
0
	Vec sample(Vec const& N, Vec const& in, Vec const& color, float sampleX, float sampleY, Vec& out, bool& specular) const
	{
		// generate ray in hemisphere
	    out = reflectedRay(N, in);
		specular = true;
		return Vec(1.f, 1.f, 1.f);
	}
Пример #3
0
Vec4d Raytracer::shade(const RayIntersection& intersection,
                      size_t depth) const
{
  // This offset must be added to intersection points for further
  // traced rays to avoid noise in the image
  const Vec3d offset(intersection.normal() * Math::safetyEps());

  Vec4d color(0,0,0,1);
  std::shared_ptr<const Renderable> renderable = intersection.renderable();
  std::shared_ptr<const Material>   material   = renderable->material();

  for(size_t i=0;i <mScene->lights().size();++i)
  {
    const Light &light = *(mScene->lights()[i].get());

    //Shadow ray from light to hit point.
    const Vec3d L = (intersection.position() + offset) - light.position();
    const Ray shadowRay(light.position(), L);

    //Shade only if light in visible from intersection point.
    if (!mScene->anyIntersection(shadowRay,L.length()))
      color += material->shade(intersection,light);
  }

  // limit recursion depth
  if (depth >= mMaxDepth)
    return color;

  Vec3d dir = reflect(intersection.ray().direction(), intersection.normal());
  Ray reflectedRay(intersection.position() + offset, dir);
  double reflectance = material->reflectance();
  color = color * (1 - reflectance) +  reflectance * trace(reflectedRay, depth - 1) + Vec4d(0.0,0.0,0.0,1.0);
  return color;
}
Пример #4
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();
}
Пример #5
0
// Light that bounces multiple times before reaching the eye
Rgb Reflector::indirectRadiance(Intersection *intersection, Ray ray, Scene *scene, int depth)
{
	Vector3 towardsViewer = ray.getDirection().normalized();
	Vector3 normal = intersection->getSurface()->computeSurfaceNormal(intersection->getIntersectionPoint()).normalized();

	Ray reflectedRay(intersection->getIntersectionPoint(),
					 towardsViewer.reflect(normal),
					 ray.getRefractiveIndex(),
					 ray.getMaxDepth());
	
	return kReflectivity * scene->trace(reflectedRay, EPSILON, depth + 1).getPixelColor();
}
Пример #6
0
RTRay RTRayTracer::genReflectionRay(RTVector d, RTVector n,RTVector closestPoint)
{
    RTVector reflectionDir = (n*2*n.dot(d))-d;
    reflectionDir.normalize();
    reflectionDir=-reflectionDir;
    double bias = 1e-4;
    RTVector aux(closestPoint+n*bias);
    RTPoint vertice(aux.getX(),aux.getY(),aux.getZ());
    RTRay reflectedRay(vertice,reflectionDir);
    return reflectedRay;

}
Пример #7
0
Vec refractedRay(Vec const& N, Vec const& I, float n)
{
	float cosi = dot(I,N);
	float rad = 1-(1-cosi*cosi)/(n*n);
	if (rad < 0) {
		// total internal reflection
		//std::cout << "T.I.R.\n";
		return reflectedRay(N, I);
	}
	float Nc = sqrt(rad) - cosi/n;
	float Ic = 1/n;
	//std::cout << Ic << ' , ' << Nc << '\n';
	return - Ic * I - Nc * N;
}
Пример #8
0
glm::vec3 Matte::pathShade(const ShadeRec& sr)const
{
	glm::vec3 incoming = -sr.ray.getDirection();
	glm::vec3 reflected;
	float pdf;
	glm::vec3 fr = diffuseBrdf->sampleF(sr,incoming,reflected,pdf);
	Ray reflectedRay(sr.hitPoint,reflected);

	glm::vec3 reflectedColor = sr.world.getTracer()->traceRay(reflectedRay,sr.depth + 1);
	fr.x *= reflectedColor.x;
	fr.y *= reflectedColor.y;
	fr.z *= reflectedColor.z;
	return fr  * glm::dot(sr.normal,reflected) / pdf;
}
Пример #9
0
// Light that bounces multiple times before reaching the eye
Rgb Dielectric::indirectRadiance(Intersection *intersection, Ray ray, Scene *scene, int depth)
{
	/*
	 *	IDEA: Set index of refraction to be the same as the airs. In this event, should go straight through
	 *		  and the towardsViewer and refracted vector should differ in sign value (ie, they will be pointing 
	 *		  in opposite directions, but parallel)
	 */


	//TODO: Might as well store the surface normal with the intersection
	Vector3 towardsViewer = -ray.getDirection().normalized();
	Vector3 normal = intersection->getSurface()->computeSurfaceNormal(intersection->getIntersectionPoint()).normalized();

	Ray reflectedRay(intersection->getIntersectionPoint(),
					 -towardsViewer.reflect(normal),
					 ray.getRefractiveIndex(),
					 ray.getMaxDepth());

	// Add refracted ray
	bool isReflected = false;
	Vector3 refractedDirection = towardsViewer.refract(normal, ray.getRefractiveIndex(), refractiveIndex, isReflected);

	Ray refractedRay(intersection->getIntersectionPoint(),
					 refractedDirection,
					 refractiveIndex,
					 ray.getMaxDepth());

	// Compute fresnel
	double fresnel = computeFresnel(towardsViewer, normal, ray.getRefractiveIndex(),  refractiveIndex);

	Rgb radiance;
	if (fresnel >= 1.0 || isReflected == true)
	{
		radiance = scene->trace(reflectedRay, EPSILON, depth + 1).getPixelColor();
	}
	else
	{
		Rgb refractedColor = scene->trace(refractedRay, EPSILON, depth + 1).getPixelColor();
		Rgb reflectedColor = scene->trace(reflectedRay, EPSILON, depth + 1).getPixelColor();

		radiance.u.a[0] = (1.0 - fresnel) * refractedColor.u.a[0] + (fresnel) * reflectedColor.u.a[0];
		radiance.u.a[1] = (1.0 - fresnel) * refractedColor.u.a[1] + (fresnel) * reflectedColor.u.a[1];
		radiance.u.a[2] = (1.0 - fresnel) * refractedColor.u.a[2] + (fresnel) * reflectedColor.u.a[2];
	}
	return kAbsorption * radiance;
}
Пример #10
0
	float3 trace(const Ray& ray, int depth)
	{
        Hit hit = firstIntersect(ray);

        // If ray hits nothing, we return the aurora borealis
		if(hit.t < 0) {
            return ray.dir * ray.dir * float3(0,1,0.6);
        }
        
        float3 lightSum = {0,0,0};

        for(LightSource *l : lightSources) {
            float3 li = l->getLightDirAt(ray.origin);
            float dist = l->getDistanceFrom(hit.position);
            int maxDepth = 5;

            // Deals with shadows
            Ray shadowRay(hit.position + (hit.normal*0.1), li);
            Hit shadowHit = firstIntersect(shadowRay);
            if(shadowHit.t > 0 && shadowHit.t < dist)
                continue;
            
            // Handles types of materials differently
            if(depth > maxDepth) return lightSum;
            if(hit.material->reflective){   // for smooth surface
                float3 reflectionDir = hit.material->reflect(ray.dir, hit.normal);
                Ray reflectedRay(hit.position + hit.normal*0.1, reflectionDir );
                lightSum += trace(reflectedRay, depth+1)
                        * hit.material->getReflectance(ray.dir, hit.normal);
            }
            if(hit.material->refractive) {  // for smooth surface
                float3 refractionDir = hit.material->refract(ray.dir, hit.normal);
                Ray refractedRay(hit.position - hit.normal*0.1, refractionDir );
                lightSum += trace(refractedRay, depth+1) * (float3(1,1,1) - hit.material->getReflectance(ray.dir, hit.normal));
            } else {                        // for rough surface
                lightSum += hit.material->shade(hit.normal, -ray.dir, l->getLightDirAt(hit.position),
                                           l->getPowerDensityAt(hit.position));
            }
        }
        
		return lightSum;
	}
Пример #11
0
    bool Scene::traceRay(Ray& ray, RenderOption option, float refractiveIndex, int level, Color* acc, HitInfo* hitInfo)
    {
        if (level > kMaxTraceLevel) {
            return false;
        }
        *acc = kColorBlack;
        
        if (m_rootGroup->hit(ray, hitInfo)) {
            Vector3 hitPosition = hitInfo->position;
            Vector3 hitNormal = hitInfo->normal;
            MaterialRef hitMaterial = hitInfo->material;
            
            if (option & RenderMaterialAmbience) {
                Color materialColor;
                if (hitMaterial->texture()) {
                    materialColor = hitMaterial->texture()->texelAt(hitInfo->uv);
                } else {
                    materialColor = hitMaterial->color();
                }

                *acc += hitMaterial->ambient() * materialColor * (1.0f - hitMaterial->transparency());
            }
            
            for (unsigned int i = 0; i < m_lights.size(); i++) {
                LightRef light = m_lights[i];
                *acc += light->luminanceOfMaterialAt(*hitInfo, this, option) * (1.0f - hitMaterial->transparency());
                
                if (option & RenderReflection) {
                    if (hitMaterial->reflectivity() > 0.0f && level < kMaxTraceLevel) {
                        float reflection = 2.0 * ray.direction().dot(hitNormal);
                        Vector3 reflectionDirection = (ray.direction() - (hitNormal * reflection)).normalize();
                        Ray reflectedRay(hitPosition, reflectionDirection);
                        
                        HitInfo reflectionInfo;
                        Color reflectedColor = kColorBlack;
                        if (traceRay(reflectedRay, option, refractiveIndex, level + 1, &reflectedColor, &reflectionInfo)) {
                            reflectedColor = reflectedColor * hitMaterial->reflectivity();
                            *acc += reflectedColor * (1.0f - hitMaterial->transparency());
                        }
                    }
                }
                
                if (option & RenderTransparency) {
                    if (hitMaterial->transparency() > 0.0f && level < kMaxTraceLevel) {
                        float n = refractiveIndex / hitMaterial->refractiveIndex();
                        float cosA = -ray.direction().dot(hitNormal);
                        float cosB = sqrtf(1.0f - n * n * (1 - cosA * cosA));
                        if (cosB > 0.0f) {
                            Vector3 refracDirection = (n * ray.direction()) + (n * cosA - cosB) * hitNormal;
                            
                            Vector3 refracRayOrigin = hitPosition + refracDirection * EPSILON;
                            Ray refracRay(refracRayOrigin, refracDirection);
                            
                            HitInfo refracInfo;
                            Color refracColor = kColorBlack;
                            if (traceRay(refracRay, option, refractiveIndex, level + 1, &refracColor, &refracInfo)) {
                                refracColor = refracColor * hitMaterial->transparency();
                                Color absorbance = hitMaterial->color() * 0.15f * -refracInfo.distance;
                                Color transparency = Color(expf(absorbance.red), expf(absorbance.green), expf(absorbance.blue));
                                refracColor = refracColor * transparency;
                                *acc += refracColor;
                            }
                        }
                    }
                }
            }
        }
        
        
        return true;
    }
Пример #12
0
glm::vec3 Dielectric::shade(const ShadeRec& sr)const
{
	glm::vec3 L;
	//glm::vec3 L = Phong::shade(sr);
	glm::vec3 reflected;
	glm::vec3 incoming(-sr.ray.getDirection());
	glm::vec3 fr = fresnelBrdf->sampleF(sr,incoming,reflected);
	Ray reflectedRay(sr.hitPoint,reflected);
	float t = 0.0f;
	glm::vec3 Lr, Lt;
	float nDotR = glm::dot(sr.normal,reflected);

	if(fresnelBtdf->tir(sr))
	{
		if(nDotR < 0.0)
		{
			//reflected ray is inside
			Lr = sr.world.getTracer()->traceRay(reflectedRay,t,sr.depth + 1);
			glm::vec3 colorFilter = glm::pow(colorFilterIn,glm::vec3(t));
			L.x += colorFilter.x * Lr.x;
			L.y += colorFilter.y * Lr.y;
			L.z += colorFilter.z * Lr.z;
		}
		else
		{
			//reflected ray is outside
			Lr = sr.world.getTracer()->traceRay(reflectedRay,t,sr.depth + 1);
			glm::vec3 colorFilter = glm::pow(colorFilterOut,glm::vec3(t));			
			L.x += colorFilter.x * Lr.x;
			L.y += colorFilter.y * Lr.y;
			L.z += colorFilter.z * Lr.z;
		}
	}
	else
	{
		//no total internal reflection
		glm::vec3 transmitted;
		glm::vec3 ft = fresnelBtdf->sampleF(sr,incoming,transmitted);
		Ray transmittedRay(sr.hitPoint,transmitted);
		float nDotT = glm::dot(sr.normal,transmitted);

		if(nDotT > 0.0)
		{
			//reflected ray is inside
			Lr = sr.world.getTracer()->traceRay(reflectedRay,t,sr.depth +1) * fabs(nDotR);
			Lr.x *= fr.x;
			Lr.y *= fr.y;
			Lr.z *= fr.z;

			glm::vec3 colorFilterR = glm::pow(colorFilterIn,glm::vec3(t));
			L.x += colorFilterR.x * Lr.x;
			L.y += colorFilterR.y * Lr.y;
			L.z += colorFilterR.z * Lr.z;

			//transmitted ray is outside
			Lt = sr.world.getTracer()->traceRay(transmittedRay,t,sr.depth +1) * fabs(nDotT);
			Lt.x *= ft.x;
			Lt.y *= ft.y;
			Lt.z *= ft.z;

			glm::vec3 colorFilterT = glm::pow(colorFilterOut, glm::vec3(t));
			L.x += colorFilterT.x * Lt.x;
			L.y += colorFilterT.y * Lt.y;
			L.z += colorFilterT.z * Lt.z;
		}
		else
		{
			//reflected ray is outisde
			Lr = sr.world.getTracer()->traceRay(reflectedRay,t,sr.depth +1) * fabs(nDotR);
			Lr.x *= fr.x;
			Lr.y *= fr.y;
			Lr.z *= fr.z;

			glm::vec3 colorFilterR = glm::pow(colorFilterOut,glm::vec3(t));
			colorFilterR.x *= Lr.x;
			colorFilterR.y *= Lr.y;
			colorFilterR.z *= Lr.z;
			L += colorFilterR;

			//transmitted ray is inside
			Lt = sr.world.getTracer()->traceRay(transmittedRay,t,sr.depth +1) * fabs(nDotT);
			Lt.x *= ft.x;
			Lt.y *= ft.y;
			Lt.z *= ft.z;

			glm::vec3 colorFilterT = glm::pow(colorFilterIn,glm::vec3(t));
			colorFilterT.x *= Lt.x;
			colorFilterT.y *= Lt.y;
			colorFilterT.z *= Lt.z;
			L += colorFilterT;
		}
	}

	return L;
}
Пример #13
0
Geometry* Raytracer::Raytrace(Ray &r, Color &col, int depth, float &dist)
{
	if(depth > TRACEDEPTH)
		return NULL;
	dist = MAX_DIST;
	Vector intersection, L, N, V, R, sampleDir, samplePos;
	Geometry *geom = NULL;
	//int result = 0;
	int res;
	float dot, diff, spec, shade = 0.0f, ldist, rdist, tempdist, ambient;
	float step = 1.0f / lrflti(shadowQuality);
	Color diffuse, specular, reflection, accumulator;
	Ray shadow, ambientRay;
	bool inShade;

	//find the nearest intersection
	vector<Geometry *> &gv = sc->GetObjects();
	for(vector<Geometry *>::iterator git = gv.begin(); git != gv.end(); git++)
	{
		if((*git)->GetType() == Geometry::BVHACCEL)
		{
			BVH *bvh = static_cast<BVH *>(*git);
			Geometry *ng = NULL;
			res = bvh->IntersectRecursive(r, dist, &ng);
			if(res)
			{
				geom = ng;
			}
		}
		else
		{
			res = (*git)->Intersect(r, dist);
			if(res)
			{
				geom = *git;
				//result = res;
			}
		}
	}

	//if there's no hit, terminate the ray
	if(!geom)
		return NULL;

	if(geom->IsLight())
	{
		col = geom->GetMaterial().GetColor() * geom->GetLightIntensity();
	}
	else
	{
		//determine the point of intersection
		intersection = r.origin + (r.direction * dist);

		//accumulate the lighting
		vector<Geometry *> &lov = sc->GetObjects();
		for(vector<Geometry *>::iterator lit = lov.begin(); lit != lov.end(); lit++)
		{
			if(((*lit)->IsLight()) && ((*lit)->GetType() == Geometry::SPHERE))
			{
				L = ((Sphere *)(*lit))->GetPosition() - intersection;
				ldist = L.Length();
				L /= ldist;

				if(geom->GetType() == Geometry::SDFUNC)
				{
					N = geom->GetNormal(intersection);
					shadow.origin = intersection + N * (10.0f * EPSILON);
				}
				else
				{
					shadow.origin = intersection + L * EPSILON;
				}

				//shadow
				if(shadowQuality == 1)
				{
               Geometry *lcache = (*lit)->GetLightCacheItem(omp_get_thread_num());
					shade = 1.0f;

					shadow.direction = L;
               
               //try shadow cache first
               bool lightCacheHit = false;
               if(lcache && (lcache->Intersect(shadow, ldist)))
               {
                  lightCacheHit = true;
                  shade = 0.0f;
               }

               //now iterate through the geometry
               if(!lightCacheHit)
               {
                  vector<Geometry *> &sov = sc->GetObjects();
                  for(vector<Geometry *>::iterator sit = sov.begin(); sit != sov.end(); sit++)
                  {
                     if((*sit != *lit) && (*sit != lcache) && ((*sit)->Intersect(shadow, ldist)))
                     {
                        (*lit)->SetLightCacheItem(*sit, omp_get_thread_num());
                        shade = 0.0f;
                        break;
                     }
                  }
               }
				}
				else
				{
					shade = 0.0f;
					int i;
					//apparently parallel shadows slows it down
					//#pragma omp parallel for default(none) shared(light, intersection, ldist, numItems, step) private(i, inShade, tempdist, shadowObj, s) firstprivate(shadow) reduction(+:shade) schedule(dynamic, 1)
					for(i = 0; i < shadowQuality; i++)
					{
                  Geometry *lcache = (*lit)->GetLightCacheItem(omp_get_thread_num());
						shadow.direction = (*lit)->GeneratePoint() - intersection;
						shadow.direction.Normalize();
						inShade = false;
						tempdist = ldist;

                  //try shadow cache first
                  bool lightCacheHit = false;
                  if(lcache && (lcache->Intersect(shadow, tempdist)))
                  {
                     lightCacheHit = true;
                     shade = 0.0f;
                  }

                  //now iterate through the geometry
                  if(!lightCacheHit)
                  {
                     vector<Geometry *> &sov = sc->GetObjects();
                     for(vector<Geometry *>::iterator sit = sov.begin(); sit != sov.end(); sit++)
                     {
                        if((*sit != *lit) && (*sit != lcache) && ((*sit)->Intersect(shadow, tempdist)))
                        {
                           (*lit)->SetLightCacheItem(*sit, omp_get_thread_num());
                           inShade = true;
                           break;
                        }
                     }
                  }

                  //update the shading
						if(!inShade)
						{
							shade += step;
						}
					}
				}

				//make sure the point isn't in a shadow
				if(shade != 0.0f)
				{
					N = geom->GetNormal(intersection);

					//diffuse
					if(geom->GetMaterial().GetDiffuse() > 0)
					{
						dot = N.Dot(L);
						if(dot > 0)
						{
							diff = dot * geom->GetMaterial().GetDiffuse();
							diffuse = geom->GetMaterial().GetColor() * (*lit)->GetMaterial().GetColor() * diff;
						}
					}

					//specular
					if(geom->GetMaterial().GetSpecular() > 0)
					{
						V = r.direction;
						R = L - N * L.Dot(N) * 2.0f;
						dot = V.Dot(R);
						if(dot > 0)
						{
							spec = powf(dot, 20.0f) * geom->GetMaterial().GetSpecular();
							specular = geom->GetMaterial().GetSpecularColor() * (*lit)->GetMaterial().GetColor() * spec;
						}
					}

					col += (diffuse + specular) * shade;
					//col += geom->GetMaterial().GetColor();
				}
			}
		} //end light loop

		//calculate ambient lighting
		if(occlusion > 0)
		{
			//setup needed for both types of AO
			ambient = 0.0f;

			//we can use really fake and fast AO for SDFs
			if(geom->GetType() == Geometry::SDFUNC)
			{
				//this type of AO calculation needs far less "rays"
				occlusion /= 12;
				if(occlusion == 0)
					occlusion = 1;

				//from Rendering Worlds With Two Triangles paper
				//ao = 1 - k * sum(1, 5, 1/(2^i) * (pink(i) - yellow(i)));
				// pink(i) = distance from intersection point to sample point along the normal
				//         = delta * i
				// yellow(i) = distance from sample point to surface
				//           = distfield(intersection + delta * i * n)
				N = geom->GetNormal(intersection);
				SDF *sdf = reinterpret_cast<SDF *>(geom);
				float sum = 0.0f;
				float k = 0.3f; // magic number for choosing overall strength of AO
				float scale = 1.0f;
				float delta = 0.1f; // magic number for sample distances
				for(int i = 1; i <= occlusion; i++)
				{
					scale *= 0.5f;
					float pink = delta * static_cast<float>(i);

					Vector sample = intersection + (N * pink);
					float yellow = sdf->distance(sample);

					sum += scale * fmax(pink - yellow, 0.0f); //note that pink >= yellow since the intersection point is the furthest possible you could go
				}
				ambient = k * (1.0f - sum);
			}
			else
			{
				//initialize the ambient light
				float u, v, sqrtv, angle, ambdist;
				bool intersected;
				Vector sampleDir;
				float invsamples = 1.0f / lrflti(occlusion);

				//shoot out cosine weighted rays
				for(int i = 0; i < occlusion; i++)
				{
					u = lrflti(rand()) * MAX_RAND_DIVIDER * TWOPI;
					v = lrflti(rand()) * MAX_RAND_DIVIDER;
					sqrtv = sqrtf(v);
					sampleDir =  Vector(cosf(u) * sqrtv, sinf(u) * sqrtv, sqrtf(1.0f - v));

					N = geom->GetNormal(intersection);
					angle = N.Dot(sampleDir);
					if(angle < 0)
					{
						sampleDir *= -1.0f;
						angle = -angle;
					}

					intersected = false;
					if(geom->GetType() == Geometry::SDFUNC)
					{
						ambientRay.origin = intersection + N * (10.0f * EPSILON);
					}
					else
					{
						ambientRay.origin = intersection + sampleDir * EPSILON;
					}
					ambientRay.direction = sampleDir;
					ambdist = MAXDEPTH;
					vector<Geometry *> &aov = sc->GetObjects();
					for(vector<Geometry *>::iterator aoit = aov.begin(); aoit != aov.end(); aoit++)
					{
						if((!(*aoit)->IsLight()) && ((*aoit)->Intersect(ambientRay, ambdist)))
						{
							intersected = true;
							break;
						}
					}

					if(!intersected)
					{
						ambient += invsamples * angle;
					}
				}
			}

			col += geom->GetMaterial().GetColor() * geom->GetMaterial().GetDiffuse() * ambient;
		}

		//get reflection
		if(geom->GetMaterial().GetReflectivity() > 0)
		{	
			if(depth < TRACEDEPTH)
			{
				/*N = geom->GetNormal(intersection);
				  R = r.direction - N * (2.0f * N.Dot(r.direction));
				  Raytrace(Ray(intersection + R * EPSILON, R), reflection, depth + 1, rdist);
				  col += reflection * geom->GetMaterial().GetColor() * geom->GetMaterial().GetReflectivity();*/

				N = geom->GetNormal(intersection);
				R = r.direction - N * (2.0f * N.Dot(r.direction));
				samplePos = intersection + R * EPSILON;
				Ray reflectedRay(samplePos, R);
				Raytrace(reflectedRay, accumulator, depth + 1, rdist);
				for(int i = 1; i < reflectionBlur; i++)
				{
					float x = ((0.2f * lrflti(rand())) / RAND_MAX) - 0.1f;
					float y = ((0.2f * lrflti(rand())) / RAND_MAX) - 0.1f;
					float z = ((0.2f * lrflti(rand())) / RAND_MAX) - 0.1f;
					sampleDir = R + Vector(x, y, z);
					sampleDir.Normalize();
					Ray sampleRay(samplePos, sampleDir);
					Raytrace(sampleRay, reflection, depth + 1, rdist);
					accumulator += reflection;
				}
				if(reflectionBlur > 1)
					accumulator /= lrflti(reflectionBlur);
				col += accumulator * geom->GetMaterial().GetColor() * geom->GetMaterial().GetReflectivity();
			}
		}
	}
	return geom;
}
Пример #14
0
Vec3f Ray::getColor(const vector <tinyobj::shape_t> &shapes,
               const vector <tinyobj::material_t> &materials,
               Vec3f lightSource)
{       
    if (DBG) cout << "[getColor] depth = " << depth << endl;
    
    //get triangle that intersect the ray
    Vec3f triangle[3];
    pair <int, int> triangleId = this->getIntersectTriangle(shapes, triangle);
    
    DBG && cout << "\t[triangleId] " << triangleId.first << ' ' << triangleId.second << endl;
    
    if (triangleId.first == -1)
    {
        DBG && cout << "\t[return] no intersection" << endl;
        return Vec3f(0.0, 0.0, 0.0);
    }
    
    Vec3f reversedDirection = this->direction * -1;
    if (dot(reversedDirection, getNormalwithRayComes(triangle, this->direction)) < 0)
    {
        DBG && cout << "[return] " << endl;
        return Vec3f(0.0, 0.0, 0.0);
    }
    
    //check if position and lightsource are in different sides of the triangle    
    Vec3f intersection;
    Vec3f color_direct;
    
    unsigned int iMaterial = shapes[triangleId.first].mesh.material_ids[triangleId.second];
    if (lineCutTrianglePlane(triangle, this->direction, this->position, lightSource))
    {
        DBG && cout << "\t[message] lineCutTrianglePlane" << endl;
        color_direct = Vec3f(0.0, 0.0, 0.0);
    }
    else
    {
        //calculate intersection
        this->intersect_remake(triangle, intersection);

        //check reflected ray
        Ray reflectedRay(intersection, lightSource - intersection, bshRoot, 0, triangleId);
        if (reflectedRay.canReach(lightSource, shapes) == false)
        {
            DBG && cout << "\t[message] reflected ray cannot reach lightsource" << endl;
            color_direct = Vec3f(0.0, 0.0, 0.0);
        }
        else
        {
            //calculate color_direct
            float radian_direct = ggx(this->position, lightSource, intersection, triangle, 1.0, 0.8, 0.8, 2.0);
            
//            color_direct = Vec3f(   (materials[iMaterial].diffuse[0] + materials[iMaterial].specular[0]) * radian_direct, 
//                                    (materials[iMaterial].diffuse[1] + materials[iMaterial].specular[1]) * radian_direct,
//                                    (materials[iMaterial].diffuse[2] + materials[iMaterial].specular[2]) * radian_direct);
            
            color_direct = Vec3f(   (materials[iMaterial].diffuse[0]) * radian_direct, 
                                    (materials[iMaterial].diffuse[1]) * radian_direct,
                                    (materials[iMaterial].diffuse[2]) * radian_direct);
            
            DBG && cout << "\t[color] " << color_direct << endl;
        }
    }

    Vec3f color_indirect(0.0, 0.0, 0.0);
    int counter = 0;
    if (depth < MAX_DEPTH)
    {        
        for (int iRay = 0; iRay < NUMBER_OF_RAYS; ++iRay)
        {
            Ray ray = this->getRandomRay_Sphere(intersection, triangle, depth + 1, triangleId);
            
//            if (triangleId.first == 4)
//                ray = this->getMirrorRay(intersection, triangle, depth + 1, triangleId);
            
//            Ray ray = this->getRandomRay_Sphere(intersection, triangle, depth + 1, triangleId);
//            Ray ray = this->getInConeRay(intersection, triangle, depth + 1, triangleId);
//            Ray ray = this->getUniformRay_Plane(intersection, triangle, depth + 1, triangleId, iRay, NUMBER_OF_RAYS);
//            Ray ray = this->getMirrorRay(intersection, triangle, depth + 1, triangleId);

            Vec3f color = ray.getColor(shapes, materials, lightSource);

            float cos_theta = dot(ray.direction, getNormalwithRayComes(triangle, this->direction));
            Vec3f w = lightSource - intersection;
            Vec3f w0 = this->position - intersection;
            Vec3f n = getNormalwithRayComes(triangle, this->direction);
            w.normalize();
            w0.normalize();
            n.normalize();
            float f_s = brdf_GGX(w, w0, n, 0.8, 0.8);
            float f_d = f_Lambert(2.0);
//            float f_d = 0;

            color_indirect += color * (f_s + f_d) * fabs(cos_theta);
//            color_indirect += color * (f_s + f_d);

            counter++;
        }

        if (counter > 0)
            color_indirect /= counter;
        
        DBG && cout << "\t[color_indirect] = " << color_indirect << endl;
    }
    
    DBG && cout << "\t[counter] " << counter << endl;

    DBG && cout << "\t[color] " << color_direct << endl;
//    color_direct = (color_direct * 0.5) + (color_indirect * 0.5);
    
    color_direct += (1.0f * color_indirect);
    for (int i = 0; i < 3; ++i)
        color_direct[i] = min(color_direct[i], 1.0f);
    
    if (this->depth == 1)
        DBG && cout << "final color = " << color_direct << endl;
    
//    return color_direct + Vec3f(materials[iMaterial].ambient[0],
//                                materials[iMaterial].ambient[1],
//                                materials[iMaterial].ambient[2]);
    
    return color_direct;
}
Пример #15
0
glm::vec3 tracer::Pathtracer::radiance(const Ray& ray, std::mt19937& engine, unsigned depth, bool considerEmission, bool debug) {
	std::uniform_real_distribution<float> distribution(0.0f, 1.0f);
	float distance, minimumDistance = std::numeric_limits<float>::max();
	Intersection tmp, isect;
	for (auto it = m_scene.begin(); it != m_scene.end(); ++it) {
		if ((*it)->intersect(ray, tmp)) {
			tmp.valid = true;
			if (debug) {
				std::cout << "testing intersection " << tmp.point << ", distance" << glm::distance2(ray.org, tmp.point) << std::endl;
			}
			if ((distance = glm::distance2(ray.org, tmp.point)) < minimumDistance) {
				minimumDistance = distance;
				isect = tmp;
			}
		}
	}
	
	if (isect.valid) {
		if (debug) { std::cout << "found intersection @ " << isect.point << ", normal: " << isect.normal << std::endl; }
		
		// russian roulette
		const material::Material& material = isect.object->getMaterial();
		glm::vec3 objectColor = material.color;
		float p = MAX(objectColor.r, objectColor.g, objectColor.b);
		if (++depth > 5) {
			if (distribution(engine) < p) {
				objectColor = objectColor / p;
			} else {
				if (considerEmission) {
					return material.emission;
				} else {
					return glm::vec3(0.0f);
				}
			}
		}
		
		if (material.type == material::Material::Type_diffuse) {
			if (debug) { std::cout << "shading diffuse material" << std::endl; }
			
			// construct orthonormal system
			float r1 = 2 * M_PI * distribution(engine);
			float r2 = distribution(engine);
			float r2s = sqrt(r2);
			glm::vec3 w = isect.normal;
			glm::vec3 u = glm::normalize( glm::cross( (fabs(w.x) > 0.1f ? ey : ex), w ) );
			glm::vec3 v = glm::normalize( glm::cross(w, u) );
			glm::vec3 d = glm::normalize((float)(cos(r1) * r2s) * u + (float)(sin(r1) * r2s) * v + (float)sqrt(1-r2) * w);
			Ray scatteredRay(isect.point+epsilon*isect.normal, d);
			if (debug) { std::cout << "tracing next ray: " << scatteredRay << std::endl; }
			
			// compose output color
			glm::vec3 color = (considerEmission ? material.emission : glm::vec3(0.0f));
			// add direct lighting contribution
			color += sampleDirectLighting(isect.point, isect.normal, objectColor, engine);
			// add indirect lighting contribution
			color += objectColor * radiance(scatteredRay, engine, depth, false, debug);
			return color;
		} else if (material.type == material::Material::Type_reflective) {
			if (debug) { std::cout << "shading reflective material" << std::endl; }
			
			Ray reflectedRay(isect.point+epsilon*isect.normal, glm::reflect(ray.dir, isect.normal));
			return material.emission + objectColor * radiance(reflectedRay, engine, depth, true, debug); 
		} else {
			error("Unhandled material type detected");
			return m_scene.getBackgroundColor();
		}
	} else {
		if (debug) { std::cout << "found no intersection" << std::endl; }
		return m_scene.getBackgroundColor();
	}
}
Пример #16
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
vec3f RayTracer::traceRay( Scene *scene, const ray& r, const vec3f& thresh, int depth )
{
	isect i;
	vec3f colorC;
	if (scene->intersect(r, i)) {
		// YOUR CODE HERE

		// An intersection occurred!  We've got work to do.  For now,
		// this code gets the material for the surface that was intersected,
		// and asks that material to provide a color for the ray.  

		// This is a great place to insert code for recursive ray tracing.
		// Instead of just returning the result of shade(), add some
		// more steps: add in the contributions from reflected and refracted
		// rays.

		const Material& m = i.getMaterial();
		vec3f intensity = m.shade(scene, r, i);
		if (depth == 0) return intensity;
		if (thresh.length() < AdaptiveThreshold) return intensity;

		vec3f Qpt = r.at(i.t);
		vec3f minusD = -1 * r.getDirection();
		vec3f cosVector = i.N * (minusD * i.N);
		vec3f sinVector = cosVector + r.getDirection();
		vec3f newThresh = thresh;

		// Reflected Ray
		if (!m.kr(i).iszero())
		{
			vec3f reflectedDirection = cosVector + sinVector;
			reflectedDirection.normalize();
			ray reflectedRay(Qpt, reflectedDirection, ray::REFLECTION);
			newThresh = prod(newThresh, i.getMaterial().kr(i)); // change the threshold value
			intensity = intensity + prod(m.kr(i), traceRay(scene, reflectedRay, newThresh, depth - 1));
		}

		//Refracted Ray
		if (!m.kt(i).iszero())
		{
			double cosineAngle = acos(i.N * r.getDirection()) * 180 / M_PI;
			double n_i, n_r;
			double criticalAngle = 360;
			int iDirection;
			// bool goingIn = true;
			// double cosThetaI = 0;
			if (cosineAngle > 90) // Coming into an object from air
			{
				n_i = 1;
				n_r = m.index(i);
				iDirection = 1;
				// cosThetaI = i.N * -1 * r.d;
			}
			else // Going out from object to air
			{
				n_i = m.index(i);
				n_r = 1;
				// goingIn = false;
				// cosThetaI = i.N * r.d;
				iDirection = -1;
			}
			
			double n = n_i / n_r;
			if (1 - n * n * (1 - (minusD * i.N) * (minusD * i.N)) > 0.0) // NO total internal refraction
			{
				vec3f sinT = n * sinVector;
				// vec3f cosT = (-1 * i.N) * sqrt(1 - sinT*sinT);
				// not sure if there are any differences between the two eqn, please check!!!!!!
				vec3f cosT = (-1 * i.N) * sqrt(1 - n * n * (1 - (minusD * i.N) * (minusD * i.N)));
				vec3f refractedDirection = cosT + iDirection*sinT;
				refractedDirection.normalize();
				ray refractedRay(Qpt, iDirection * refractedDirection, ray::REFRACTION);
				newThresh = prod(newThresh, i.getMaterial().kt(i)); // change the threshold value
				intensity = intensity + prod(m.kt(i), traceRay(scene, refractedRay, newThresh, depth - 1));
			}
		}
		colorC = intensity;
	}
	else {
		// No intersection.  This ray travels to infinity, so we color
		// it according to the background color, which in this (simple) case
		// is just black.
		colorC = vec3f (0.0, 0.0, 0.0);
	}
	return colorC;
}