// // Created by Göksu Güvendiren on 2019-05-14. // #include "Scene.hpp" void Scene::buildBVH() { printf(" - Generating BVH...\n\n"); this->bvh = new BVHAccel(objects, 1, BVHAccel::SplitMethod::NAIVE); } Intersection Scene::intersect(const Ray &ray) const { return this->bvh->Intersect(ray); } void Scene::sampleLight(Intersection &pos, float &pdf) const { float emit_area_sum = 0; for (uint32_t k = 0; k < objects.size(); ++k) { if (objects[k]->hasEmit()){ emit_area_sum += objects[k]->getArea(); } } float p = get_random_float() * emit_area_sum; emit_area_sum = 0; for (uint32_t k = 0; k < objects.size(); ++k) { if (objects[k]->hasEmit()){ emit_area_sum += objects[k]->getArea(); if (p <= emit_area_sum){ objects[k]->Sample(pos, pdf); break; } } } } bool Scene::trace( const Ray &ray, const std::vector &objects, float &tNear, uint32_t &index, Object **hitObject) { *hitObject = nullptr; for (uint32_t k = 0; k < objects.size(); ++k) { float tNearK = kInfinity; uint32_t indexK; Vector2f uvK; if (objects[k]->intersect(ray, tNearK, indexK) && tNearK < tNear) { *hitObject = objects[k]; tNear = tNearK; index = indexK; } } return (*hitObject != nullptr); } // Implementation of Path Tracing Vector3f Scene::castRay(const Ray &ray, int depth) const { // TO DO Implement Path Tracing Algorithm here Intersection p_inter = intersect(ray); if(!p_inter.happened) { return Vector3f(); } if (p_inter.m->hasEmission()) { return p_inter.m->getEmission(); } float EPLISON = 0.0001f; Vector3f l_dir; Vector3f l_indir; Intersection x_inter; float pdf_light = 0.0001f; sampleLight(x_inter,pdf_light); Vector3f p = p_inter.coords; Vector3f x = x_inter.coords; float ws_distance = (x-p).norm(); Vector3f ws_dir = (x-p).normalized(); Vector3f N = p_inter.normal.normalized(); Vector3f NN = x_inter.normal.normalized(); Vector3f emit = x_inter.emit; Ray ws_ray(p,ws_dir); Intersection ws_ray_inter = intersect(ws_ray); if(ws_ray_inter.happened&&(ws_ray_inter.distance-ws_distance)<1e-2) { l_dir=emit * p_inter.m->eval(ray.direction,ws_ray.direction,N) * dotProduct(ws_ray.direction,N) * dotProduct(-ws_ray.direction,NN) /std::pow(ws_distance,2) /pdf_light; } if(get_random_float()>RussianRoulette) { return l_dir ; } l_indir =0.0; Vector3f wi_dir =p_inter.m-> sample(ray.direction,N).normalized(); Ray wi_ray(p_inter.coords,wi_dir); Intersection wi_inter = intersect(wi_ray); if(wi_inter.happened && (!wi_inter.m->hasEmission())) { l_indir = castRay(wi_ray,depth+1) * p_inter.m->eval(ray.direction,wi_dir,N) * dotProduct(wi_dir,N) /p_inter.m->pdf(ray.direction,wi_ray.direction,N) /RussianRoulette; } return l_dir+l_indir; }