CC BY 4.0 (除特别声明或转载文章外)
如果这篇博客帮助到你,可以请我喝一杯咖啡~
作业7介绍路径追踪
说老实话,还有点不懂,辐射度量学这块好像听了两遍了,好像也就是安装模型在数学上把模型求解出来就行了,然后,加了一个多线程处理,自己不咋会,但是确实快。
这次实验其实就只需要实现castRay函数。框架给了许多需要用的函数,包括求一条光线与场景的交点intersect()。 sampleLight()在场景的所有光源上按面积uniform地sample一个点,并计算该采样的概率密度pdf。sample()按照材质的性质,给定入射方向和法向,用某种分布采样一个出射方向,其实就是光打到物体上,物体再反射一个光回来。pdf(),给定一对入射、出射方向与法向量,计算sample方法得到该出射方向的概率密度。eval(),给定一对入射、出射方向和法向量,计算f_r的值。
渲染方程
伪代码:
code:
// Implementation of Path Tracing
Vector3f Scene::castRay(const Ray &ray, int depth) const
{
// TO DO Implement Path Tracing Algorithm here
Vector3f L_dir,L_indir;
Intersection inter = intersect(ray);
//不相交
if(!inter.happened) {
return L_dir;
}
//物体是光源,直接反射物体的能量
if(inter.m->hasEmission()) {
return inter.m->getEmission();
}
//与物体相交,计算物体的直接光照和间接光照
Vector3f p = inter.coords;//物体的位置
Material* m = inter.m;//物体的材质
Vector3f N = inter.normal.normalized();//法向量
Vector3f w0 = ray.direction;//光线方向
float pdf_L = 1.0;//pdf概率密度
Intersection light_inter;
sampleLight(light_inter,pdf_L);//场景的所有光源进行采样
Vector3f x = light_inter.coords;//光源的坐标
Vector3f ws = (x-p).normalized();//物体到光源的方向
Vector3f NN = light_inter.normal.normalized();//光源的法向量
Vector3f emit = light_inter.emit;//能量
float d = (x-p).norm();
Ray Obj2Light(p,ws);//一条从物体打到光源的反射光线
float d2 = intersect(Obj2Light).distance;
if(d2-d > -0.001) {//判断中间有不有障碍物,没有就直接计算直接光照
Vector3f eval = m->eval(w0,ws,N);
float cos_theta = dotProduct(N,ws);
float cos_theta_x = dotProduct(NN,-ws);//负号原因看上图
L_dir = emit*eval*cos_theta*cos_theta_x/pow(d,2)/pdf_L;
}
float P_RR = get_random_float();//计算间接光照,也就是打到物体上
if(P_RR<RussianRoulette) {//俄罗斯轮盘,赌狗,最后除以一个概率,防止能量损失,但是会有噪声。
Vector3f wi = m->sample(w0,N).normalized();//按照物体的材质,采样一条出射方向
Ray r(p,wi);//渲染处物体到物体反射的光打到的物体的光线,也就是间接光照
Intersection inter_ind = intersect(r);
if(inter_ind.happened&&!inter_ind.m->hasEmission()) {
Vector3f eval = m->eval(w0,wi,N);
float pdf_0 = m->pdf(w0,wi,N);
float cos_theta = dotProduct(wi,N);
L_indir = castRay(r,depth+1)*eval*cos_theta/pdf_0/RussianRoulette;
}
}
return L_dir+L_indir;
}
感觉还不是特别明白…