1

因此,用于路径跟踪的 Wikipedia 页面 ( http://en.wikipedia.org/wiki/Path_tracing ) 包含该算法的简单实现,下面有以下解释:

“然后必须对所有这些样本进行平均以获得输出颜色。请注意,这种始终在法线半球中对随机光线进行采样的方法仅适用于完全漫反射表面。对于其他材料,通常必须使用重要性采样,即概率根据 BRDF 的分布选择一条新光线。例如,完美的镜面(镜面)材料不适用于上述方法,因为新光线是正确反射光线的概率 - 这是任何辐射通过的唯一光线将被反射 - 为零。在这些情况下,必须根据蒙特卡洛积分将反射率除以采样方案的概率密度函数(在上面的天真情况下,没有特定的采样方案,因此 PDF 变为结果是 1)。"

我难以理解的部分是粗体部分。我熟悉 PDF,但我不太确定它们如何融入这里。如果我们坚持镜像示例,我们将除以的 PDF 值是多少?为什么?如果我使用任意 BRDF 值(例如 Phong 反射模型或 Cook-Torrance 反射模型等),我将如何找到要除以的 PDF 值?最后,为什么我们要除以 PDF 而不是乘?如果我们分开,我们不是给概率较低的方向更多的权重吗?

4

2 回答 2

3
  1. 假设我们只有没有颜色的材料(灰度)。然后,它们在每个点的 BDRF 可以表示为单值函数

    float BDRF(phi_in, theta_in, phi_out, theta_out, pointWhereObjWasHit);
    

    这里phitheta是所考虑的两条射线的方位角和天顶角。对于纯朗伯反射,此函数如下所示:

    float lambertBRDF(phi_in, theta_in, phi_out, theta_out, pointWhereObjWasHit)
    {
        return albedo*1/pi*cos(theta_out);
    }
    

    albedo范围从 0 到 1 - 这测量了重新发射了多少入射光。该因子1/pi确保 BRDF 在所有传出向量上的积分不超过 1。使用 Wikipedia 文章 ( http://en.wikipedia.org/wiki/Path_tracing ) 的简单方法,可以按如下方式使用此 BRDF:

    Color TracePath(Ray r, depth) {
    /* .... */ 
    Ray newRay;
    newRay.origin = r.pointWhereObjWasHit;
    newRay.direction = RandomUnitVectorInHemisphereOf(normal(r.pointWhereObjWasHit));     
    Color reflected = TracePath(newRay, depth + 1);
    return emittance + reflected*lambertBDRF(r.phi,r.theta,newRay.phi,newRay.theta,r.pointWhereObjWasHit);
    }
    
  2. 正如文章和罗斯所提到的,这种随机采样是不幸的,因为它跟踪入射方向(newRay's),从那里反射的光线很少,其概率与来自大量光线的方向的概率相同。相反,应优先选择将大量光反射到观察者的方向,以便在所有方向上对最终颜色的每个贡献具有相等的采样率。为此,需要一种从概率分布中生成随机射线的方法。假设有一个函数可以做到这一点;此函数将所需的 PDF(理想情况下应等于 BDRF)和入射光线作为输入:

    vector RandomVectorWithPDF(function PDF(p_i,t_i,p_o,t_o,point x), Ray incoming)
     {
       // this function is responsible to create random Rays emanating from x
       // with the probability distribution PDF. Depending on the complexity of PDF, 
       // this might somewhat involved. It is possible, however, to do it for Lambertian
       // reflection (how exactly is math, not programming):
       vector randomVector;
       if(PDF==lambertBDRF)
       {
         float phi = uniformRandomNumber(0,2*pi);
         float rho = acos(sqrt(uniformRandomNumber(0,1)));
         float theta = pi/2-rho;
         randomVector = getVectorFromAzimuthZenithAndNormal(phi,zenith,normal(incoming.whereObjectWasHit));
       }
       else // deal with other PDFs
       return randomVector;
     }     
    

    例程中的代码TracePath将如下所示:

     newRay.direction = RandomVectorWithPDF(lambertBDRF,r);
     Color reflected = TracePath(newRay, depth + 1);
     return emittance + reflected;
    

    由于在选择样本时首选明亮的方向,因此您不必通过将 BDRF 作为比例因子应用到reflected. 但是,如果 PDF 和 BDRF 由于某种原因不同,您将不得不在 PDF>BDRF 时缩小输出(如果您从各自的方向选择了很多)并在选择为 little 时增强它。在代码中:

    newRay.direction = RandomVectorWithPDF(PDF,r);
    Color reflected = TracePath(newRay, depth + 1);
    return emittance + reflected*BDRF(...)/PDF(...);
    

    但是,如果BDRF/PDF等于 1,则输出是最好的。

  3. 问题仍然是为什么不能总是选择与 BDRF 完全相等的完美 PDF?首先,一些随机分布比其他分布更难计算。例如,如果albedo参数有轻微的变化,那么算法对于非朴素采样的效果仍然比均匀采样要好得多,但是BDRF/PDF对于微小的变化需要校正项。有时,甚至可能根本无法做到。想象一个具有不同反射行为的红色绿色和蓝色的彩色对象 - 您可以分三遍渲染,每种颜色一个,或者使用平均 PDF,它大致适合所有颜色分量,但没有一个完美。

  4. 如何实现像 Phong 着色这样的东西?为简单起见,我仍然假设只有一种颜色分量,并且漫反射与镜面反射的比率为 60% / 40%(环境光的概念在路径跟踪中没有意义)。然后我的代码将如下所示:

    if(uniformRandomNumber(0,1)<0.6)    //diffuse reflection
    {
       newRay.direction=RandomVectorWithPDF(lambertBDRF,r);
       reflected = TracePath(newRay,depth+1)/0.6;
    }
    else //specular reflection
    {
       newRay.direction=RandomVectorWithPDF(specularPDF,r);
       reflected = TracePath(newRay,depth+1)*specularBDRF/specularPDF/0.4;
    }
    return emittance + reflected;
    

specularPDF是一个在反射光线(theta_in=theta_out,phi_in=phi_out+pi)周围有一个窄峰的分布,可以使用一种方法来创建随机向量,并specularBDRF从 Phong 的模型(http://en.wikipedia )返回镜面反射强度.org/wiki/Phong_reflection_model)。请注意 PDF 如何分别被 0.6 和 0.4 修改。

于 2013-10-09T20:53:44.067 回答
1

我绝不是光线追踪方面的专家,但这似乎是经典的蒙特卡洛:

你有很多可能的光线,你随机均匀地选择一个,然后在多次试验中取平均值。您用来选择其中一条光线的分布是均匀的(它们的可能性相同),因此您不必进行任何巧妙的重新归一化。

然而,也许有很多可能的光线可供选择,但只有少数可能会导致有用的结果。因此,我们倾向于选择那些概率较高的“有用”可能性,然后重新归一化(我们不是统一选择光线更多,所以我们不能只取平均值)。这是重要性抽样。

镜像示例似乎如下:只有一条可能的光线会给出有用的结果。如果我们随机选择一条射线,那么我们击中那条有用射线的概率为零:这是连续空间上的条件概率的一个属性(它实际上不是连续的,它是由您的计算机隐式离散的,所以它并不完全正确......) :当有无限多的东西时,击中特定东西的概率必须为零。

因此,我们正在通过概率为零的事物重新归一化 - 当我们考虑概率为零的事件时,标准条件概率定义会中断,这就是问题所在。

于 2013-10-07T15:47:59.857 回答