127 lines
3.1 KiB
C++
127 lines
3.1 KiB
C++
|
//
|
||
|
// 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<Object*> &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;
|
||
|
|
||
|
|
||
|
|
||
|
}
|