【问题标题】:Path Tracing algorithm - Need help understanding key point路径追踪算法 - 需要帮助理解关键点
【发布时间】:2013-10-05 10:59:27
【问题描述】:

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

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

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

【问题讨论】:

  • 我只能假设这与更高的反射率意味着更有可能朝特定方向前进的事实有关。因此,您将反射率除以 PDF 以缩小可能的结果。

标签: algorithm graphics 3d rendering probability


【解决方案1】:
  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. 正如文章和 Ross 所提到的,这种随机采样是不幸的,因为它跟踪入射方向 (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)模型(http://en.wikipedia.org/wiki/Phong_reflection_model)。 请注意 PDF 如何分别被 0.6 和 0.4 修改。

【讨论】:

  • 函数RandomUnitVectorInHemisphereOfgetVectorFromAzimuthZenithAndNormal 将如何查找此示例?
  • RandomUnitVectorInHemisphere 看起来总是一样的:选择方位角:float phi = uniformRandomNumber(0,2*pi); 和仰角:float rho = acos(sqrt(uniformRandomNumber(0,1)));(注意rho 的分布如何偏爱小角度,因为在小仰角。然后天顶角为theta=rho-pi/2(之前缺少)。对于getVectorFromAzimuthZenithAndNormal,选择一个任意但固定的基矢量x与法线正交,并将其旋转phi以获得新矢量y...(在下一条评论中继续)
  • 最后,得到一个垂直于normaly(即cross(normal,y))的向量,并围绕这个向量将normal旋转theta。结果是在normal 指定的半球体中具有所需天顶角和方位角的向量。
  • 感谢您到目前为止的解释!您认为选择与法线正交的向量的最佳方法是什么?
  • 取两个分量,其中至少一个不为零,切换它们并反转其中一个的符号,将第三个分量设置为零:(x,y,z) -> (y ,-x,0) 或 (z,0,-x) 或 (0,z,-y) 应该都可以工作,如果不是两个交换的组件都为零。
【解决方案2】:

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

你有很多可能的光线,你随机均匀地选择一个,然后在多次试验中取平均值。 您用来选择其中一条光线的分布是均匀的(它们的可能性相同) 所以你不必做任何聪明的重新规范化。

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

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

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

【讨论】:

    猜你喜欢
    • 2021-09-30
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 2018-11-06
    • 2012-07-11
    • 2020-01-20
    相关资源
    最近更新 更多