作业7 路径追踪

作业7介绍路径追踪

enter image description here enter image description here

说老实话,还有点不懂,辐射度量学这块好像听了两遍了,好像也就是安装模型在数学上把模型求解出来就行了,然后,加了一个多线程处理,自己不咋会,但是确实快。

这次实验其实就只需要实现castRay函数。框架给了许多需要用的函数,包括求一条光线与场景的交点intersect()。 sampleLight()在场景的所有光源上按面积uniform地sample一个点,并计算该采样的概率密度pdf。sample()按照材质的性质,给定入射方向和法向,用某种分布采样一个出射方向,其实就是光打到物体上,物体再反射一个光回来。pdf(),给定一对入射、出射方向与法向量,计算sample方法得到该出射方向的概率密度。eval(),给定一对入射、出射方向和法向量,计算f_r的值。

渲染方程

enter image description here enter image description here

伪代码:

enter image description here

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;
}

感觉还不是特别明白…