• GAMES101 路径追踪


    参考文章

    渲染方程

            渲染方程描述了光线传播的方式:考虑到从某一角度观察空间中任何一个点的颜色,由自身发出来的光和反射出来的光组成。(反射出来的光:是从空间中任何一个方向接收到的光经过BRDF后从观察的方向反射出来)

     

    蒙特卡洛积分

    目的:给出任何一个函数求解它的定积分(适用于难以求解的函数)

     

            蒙特卡洛积分实质是一种随机的采样方法,我们假设函数曲线变为常数函数,在积分域内不断采样,将采样的结果作为整个函数区间的常数估计,将多次采样结果求平均作为定积分的求解结果估计。

    即使用随机变量 Xi 去采样积分区间,随机变量的PDF为 p(x) 得到近似结果:

     

     


    Path Tracing

    到此我们终于引入了路径追踪的概念,首先我们回顾一下Ray Tracing

    在前文中讲的光线追踪全称为 Whitted-Style Ray Tracing,它的光线弹射有两种情况:

    • 光线在光滑表面发生完美的镜面反射或折射
    • 光线在漫反射表面停止

    但这样的假设是不正确的,Whitted-Style Ray Tracing存在一系列不符合物理真实的问题:

    • 无法表现Glossy的材质效果(非完全镜面的反射表面)

     

    • 忽略了漫反射物体的后续反射,导致在漫反射物体之间的光线无法表现(左侧天花板是黑色的,并且无反射的面的颜色)

     

    由此,Whitted-Style Ray Tracing是不够正确的,但是渲染方程是完全按物理推导了,它是正确的:

     

            但是要求解准确的渲染方程存在两个问题,首先需要求解一个半球面上的积分,其次渲染方程的计算是一个递归的问题。

            对于求解半球面的定积分这一问题,我们采用蒙特卡洛积分方法。首先我们考虑一个简单场景,只考虑一个着色点的直接光照:

     

            ω0 是我们的观察方向, ωi 是四面八方的光线入射方向(仍然认为是从着色点发出向外的),然后我们来求解这个点的直接光照(假设其不发光,也先不考虑多次反射):周围接受的光经过BRDF作用后反射到观察方向上的光。

     

            本质上就是要求解一个半球面上的定积分问题,所以我们使用蒙特卡洛方法来求解。那么我们需要定义目标函数 f(x) 以及我们对球面采样的概率密度分布函数 p(ωi) ,先假设为最简单的均匀采样方法:

             已知f和pdf所以可以直接蒙特卡洛积分:

     

    由此可以写出着色点出射radiance的算法:

    如果只考虑直接光照的话,我们的path tracing就到此结束了(是不是很简单

    接下来我们引入间接光照部分,如果我们的随机采样点的光线打到了其他物体而不是光源我们该如何考虑:

     

    当我们需要求解Q—>P—>观察点的间接光照时,我们需要知道Q点反射到P点的光照强度,就相当于我们将观察点变为P点求解Q处的直接光照,那么要实现全局光照的路径追踪,只需要在刚刚的算法中加入一个采样光线打到其他物体的分支变为一个递归算法:

     

    但是这样的方法仍存在一些问题:

    • 光线数量会爆炸

    光线弹射多方向采样的过程是一个指数增长的过程:

     

    要解决这个问题,当 N =1 才不会指数爆炸:

     这就叫做路径追踪。


    如果N不为1,称为分布式路径追踪,就存在光线爆炸的问题,但是N 为1 的情况会对结果带来较大的噪声,如何解决?

    考虑我们最终需要得到的结果是一个像素的radiance的值,穿过一个像素可以有多条path,我们只需要在同一像素内进行采样,对每个采样点获得一个path,将着色结果求平均即可(为什么叫path:光线在采样后只会朝着一个方向进行传播和反射,最终会形成一条连接视点和光源的路径)。

     

     

    到此为止我们解决了求解积分的问题,然后还剩下最后一个问题,就是这个递归问题的求解。求解递归问题需要两个条件,一是问题可转移,二是停止条件。目前这个算法的问题是它的递归永远不会停止。

    但是我们不能提前限制光线的弹射次数,因为现实中的光线弹射本身就是没有次数限制的,我们的人为限制会导致人为的能量损失。为解决这个困境,人们引入了一种方法:俄罗斯轮盘赌。

    Russian Roulette

    大家在西部电影中应该都看过这个情节,赌徒在左轮手枪中装入子弹,轮流朝自己开枪,博取生存概率。我们引入这样的概念表示在光线追踪过程中我们以一定的概率去停止往下继续追踪。

    我们求解最后着色点的 radiance,期望获得精确的计算结果,同时又希望递归可以终止,由此我们定义一个概率 P 我们去继续往下打出光线做追踪,将其返回结果除以P,(1-P)的概率不继续追踪得到的结果是0,而这是一个简单的离散随机变量,可以求得结果的期望值不变,即无偏估计。

     

    由此我们的算法改为:

     

    至此,我们获得一个正确的Path Tracing的方法,但是这不是一个非常高效的算法,我们具体看下,引入采样率 SPP 的概念(samples per pixel),当spp较小时,会得到noisy的结果

     

    为了提高算法的效率,我们期望在 Low SPP 的结果下仍然能得到低噪声的结果。那么要如何改进呢?我们先理解一下算法效率不高的原因:

     

    对于同样的着色点,光源范围小会导致大量的随机采样的光源浪费资源。由此我们可以思考另外一种减少对光线的浪费的采样方法。可以发现,如果我们直接在光源上采样,那么得到的所有采样光线都不会被浪费。

    假设存在一个面积为 A 的面光源,我们在光源上进行均匀采样,那么 pdf=1/A

    由于渲染方程是定义在球面立体角上的积分,同时蒙特卡洛方法要求采样域与积分域统一,由此我们需要把渲染方程的积分域改写为光源:

     

    所以我们需要找到 dA 与 dω 的关系:由数学关系可以得到,我们将光源上单位面积 dA 投影到球面上,就可以得到相应的立体角

     

    由此我们可以重写渲染方程:

     

    转换为了在光源积分,在光源采样。

    在推导出了光源采样的方法后我们再来进一步改进原始的算法,我们将入射的radiance分为两部分:

    • 来自光源的部分(直接光照,我们可以直接采用光源采样)
    • 来自其他物体的反射(间接,仍然采用RR)

     

    到此,路径追踪就终于结束啦!

  • 相关阅读:
    centos7 安装python3.10及配置软连接
    Gradle
    中国日用化工市场竞争格局展望及未来战略分析报告2022年版
    json-server搭建mock服务
    【ESP32】VScode + platformIO 环境搭建
    Typescript给定一个由key值组成的数组keys,返回由数组项作为key值组成的对象
    45.讲位图:如何实现网页爬虫中的URL去重功能
    姓氏起源查询易语言代码
    神经网络 | 深度学习背后的数学
    【JavaEE初阶】 线程安全的集合类
  • 原文地址:https://blog.csdn.net/qq_48626761/article/details/126903753