计算机图形学入门23:蒙特卡洛路径追踪

news2024/12/30 2:15:20

1.前言

        前面几篇文章介绍了Whitted-style光线追踪,还介绍了基于物理渲染的基础知识,包括辐射度量学、BRDF以及渲染方程,但并没有给出解渲染方程的方法,或者说如何通过该渲染方程计算出屏幕上每一个坐标的像素值。

        Whitted-style光线追踪是存在很多不正确的情况,但是基于渲染方程是正确的。本文就介绍通过蒙特卡洛路径追踪来解渲染方程的方法。

2.蒙特卡洛积分

        蒙特卡洛积分(Monte Carlo Integration)是为了解决函数的定积分。给任意函数要算出这个函数的定积分,而定积分是一个数值。下面举个例子,如下图所示,如何去求曲线在a、b之间围成的面积。

        求曲线在a、b区域内面积也就是求曲线的函数在[a, b]内的定积分。但对于这样一个曲线,很难用一个数学函数去表示,因此无法用一般解析的方法直接求得积分值,可以采用黎曼积分的思路。

        也就是对上图这个图形纵向均匀地切割,分成多个宽度相同的条形,那么这些条形就可以近似为长方形,取条形中线的高度作为近似长方形的高度,将这些近似小长方形的面积全部加起来就能得到整个图形近似的面积。

        当切割的数量越多也就是采样越多,得到的结果越逼近真实的数值。

        而相比起黎曼积分的均匀采样,蒙特卡洛积分可以指定一个随机分布来对被积分的值进行采样,因此更加通用,定义如下。

        如上图所示,我们希望求出一个函数f(x)在积分域[a,b]上的积分值,选定一个采样的分布p(x),通过对该分布来进行多次的函数值采样,最后近似的积分值如图中最下方式子所示。

        注意公式中的1/N可以理解为不将图形分割,而是每次采样都近似为一个采样对应的函数值的长方形,将多次采样近似的长方形面积累加求均值,如下图是采样次数为4时的。

        这里对前面的公式进行一个简单的推导,从概率论的角度理解,求均值的做法其实也是对期望的逼近。

        那么对于这样一个服从某一分布的期望的计算套公式直接计算得。

        通过以上推导即可明白蒙特卡洛的近似正是对积分值的一个无偏估计,也就是采样次数越多,近似值与积分值越接近。简单说就是样品越多,反差越小

        为了方便,一般都使用均匀采样,因此很容易推出。

        因此,蒙特卡洛就是对函数值进行多次采样求均值,从而帮助求得困难积分值的近似的方法

3.蒙特卡洛路径追踪

3.1 Whitted-style光线追踪的问题

          在前面的文章中学过Whitted-style光线追踪主要是不断在弹射光线,那么是怎么弹射光线的?

        1.当光线打到表面为光滑的物体上,比如玻璃,那么光会沿着镜面方向反射或者沿着折射方向折射。

        2.当光线打到漫反射物体上,光线就停了。

        那么,这两个简化是对的吗?

        其实,这个不一定是对的,下面举例了几个光线追踪的问题。那么,就有了路径追踪(Path Tracing)来解决很多基于非物体或者不正确的问题。

        1.whited-style光线追踪对于反射表面进行镜面反射,难以模拟介于漫反射和镜面反射之间的光泽反射(Glossy Reflection)。

        对于有光泽的材料,光线应该反射到哪里?如下图所示。

        2.whited-style光线追踪对于漫反射表面直接进行光照计算,并没有对漫反射的光线进行追踪。

        whited-style光线追踪把光线打到漫反射物体上,光线就停了,但是实际上还是有光线会反射不同方向上去。如下图所示,直接光照与全局光照的区别,全局光照图上可以看到红色和绿色墙面的颜色反射到了中间的物体表面上。

3.2 解渲染方程

3.2.1 解渲染方程的难点

        上面介绍了whited-style光线追踪存在的问题,但是渲染方程是正确的,回顾渲染方程使用了各种辐射度量学、BRDF提供标准来推导出来的,方程如下。

        要想解出渲染方程的解主要有两个难点:

        1.半球积分的计算。考虑来至四面八方的光照,就要求整个半球(不考虑背面光)的积分。

        2.递归形式。反射来的光线有可能是直接光照,也可能是其他物体反射来的间接光照。

        对于第一个问题,考虑到如何用一个数值来解一个积分,就需要用到前面所学的蒙特卡洛积分了。

3.2.2 一个简单的蒙特卡洛解决方案

        假设我们在以下场景中渲染一个像素(点),仅用于直接光照,场景中为面光源,如下图所示。其中ω0为眼睛的观察方向,ωi则是各个方向弹射到点 的光线(这里箭头方向与光线实际方向相反是因为渲染方程中所有方向都以表面向外为正方向)。

        先对渲染方程稍微做一下滥用,舍弃自发光项(假设除了光源其他物体不会发光),从而方便进行计算推导如下。由于限定了直接光照,所以四面八方来的光只有光源自身发射的。其物理含义为着色点 到摄像机或人眼的Radiance值。

        这个方程看起来很复杂,其实就是一个半球在不同方向上的积分,所以就用蒙特卡洛积分来求值

        回想前面所提到的,对于一个困难积分只要选定一个被积分变量的采样分布即可通过蒙特卡洛的方法得到积分结果的近似值。而此时的被积分值为入射光线方向ωi,选定采样分布p(ωi)为在 点的半球方向内对ωi进行均匀取样(只考虑从平面上方入射的光线,半球的立体角为2π,p(wi)为1/2π),不难得出积分近似结果如下:

        到此时可以算出任何一个着色点出射的Radiance。对这个着色点 p 出射方向为w_{o},要计算来至四面八方光线对这个点直接光照的贡献,就可以写出一个算法,如下伪代码所示。

        L_i 代表光源亮度(Radiance),f_r 代表BRDF,pdf(wi) 代表均匀采样的值。

3.2.3 全局照明

        上述只考虑直接光照显然是不够的,还需要间接光照,即当采样的ωi方向碰撞到了别的物体,如下图所示。

        此时采样的光线ωi碰撞到了另一个物体的Q点,如果这条光线在Q点反射后没有碰到光源,这条路径自然没有贡献;如果光线在Q点反射后碰到了光源,那么该条路径对着色点P的贡献是多少呢?

        此时可以理解为ωi方向为Q点的观察方向,求Q点到ωi方向的Radiance值,也就是光源在点Q的直接光照再乘上Q点发射到ωi方向的比例。

        显然这是一个类似光线追踪的递归过程,不同点是该方法通过对光线方向的采样从而找出一条条可以连接眼睛和光源的的光线路径,这也正是为什么叫路径追踪的原因,伪代码如下:

        在Q点反射过来的Radiance,就相当于在Q点反射过来的直接光照,也就是在Q点从-wi方向看过去的直接光照。这里是-wi方向是因为从P点到Q点是wi方向,那么从Q点到P点自然就是-wi

        至此,我们成功通过蒙特卡洛的方式解出(近似)了渲染方程的积分值,也通过考虑直接光照与间接光照解决了递归的问题。到此,是否已经解决了?

3.2.4 路径追踪(Path Tracing)

        接上述疑问,还有两个问题。

        1.随着反射增加,射线爆炸

        如下图所示,我们通过每次对光线方向的采样从而解出方程,假设有一条光线打到物体上,为了计算直接光照,假如从物体上打出100条光线,那么100条都有可能打到其他物体上,在其他物体上又要算直接光照,那么每条再发射100条光线,就是10000条,依次类推,反射越多次光线数量便会指数级爆炸增长,计算量完全无法接受,那么如何才能使得光线数量不爆炸增长呢?

        唯有每次只采样一个方向,也就是N = 1(1的多少次方都是1)。N = 1时就是通常所说的路径追踪(连接一条视点与光源的路径),作为区分N != 1时,一般称为分布式路径追踪

        从现在开始,我们总是假设每个着色点只有一条光线被追踪,伪代码如下。

        如果只采样一个方向那么所带来的问题也是显而易见的,积分计算的结果会非常的随机,虽然蒙特卡洛积分是无偏估计,但样本越少显然偏差越大。

        但该问题也好解决,如果每次只去寻找一条路径结果不准确,那么就去寻找多条路径。如下图所示,分别有红、蓝、黑三条路径。

        从摄像机向每个像素的区域内发射多条路径,追踪每条路径的反射并计算,最后将多条路径的结果求平均即可。伪代码如下。

        到此解决了射线爆炸问题,但还没有彻底解决,因为shade函数的递归没有出口,永远不会停下。

        因为在现实中光线是经过无数次反射的,如果在这里给光线追踪算法中设定最大反射次数的方式,这样就会导致能量损失,所以这里非常精妙的采用了俄罗斯轮盘赌(Russian Roulette)

       一把弹仓6发的左轮手枪,随机填充两发子弹,按下扳机时,目标有4/6的概率活下来,这就是俄罗斯轮盘赌的概念。

        假设一个着色点出射的结果为Lo,期望递归停止后返回的结果还是Lo。那么,首先设定一个概率P(0<P<1),每次光线反射时有P的概率光线会继续递归并设置返回值为Lo/P,有1-P的概率光线停止递归,并返回0。这样巧妙的设定之下光线一定会在某次反射之后停止递归,并且计算的结果依然是无偏的,因为从概率论的角度来看,Radiance的期望Lo不变,证明如下。

        shade函数的伪代码变更如下。

        至此,路径追踪算法已经完成大半,只差最后一个小问题!

        2.现在的路径追踪效率非常的低下

        如下图所示,图中顶部为面光源,中间为遮挡物。左图表示每个像素使用更少的采样(Low SPP),右图是每个像素使用更高的采样(High SPP)。可以发现采样点更多,效果越好,越干净(噪点少),所以效率很低,最好在Low SPP情况下也能达到很好的效果。有没有办法呢?

        其实是有办法提高效率的,如下图所示就是造成低效率的原因。

        在每次计算直接光照的时候,通过均匀采样随机方向打出光线,但只有极少数的光线方向可以碰到光源,尤其当光源越小的时候,这种现象越明显,大量采样的光线都是无效浪费的。

        蒙特卡洛方法允许任何采样方法,不仅限于均匀采样。因此我们可以直接对光源进行采样(如果没有别的物体遮挡,光线没有被“浪费”)。

        假设光源的面积为A,那么对光源进行的采样分布p(A) = 1/A (因为光源面积p(dA)积分起来为1),但原始的渲染方程:

        很明显是对光线方向ωi进行积分的,如果想要对光源进行采样并依然使用蒙特卡洛的方法,那么一定要将其修改为对光源面积 dA 的积分(改变积分域),换言之就是需要找到 dA 与 dω 的关系。如下图所示。

        dA 与 dω 的关系如下。

        关系式中的 cosθ’ 是为了计算出光源上微分面积元正对半球的面积,之后再按照立体角的定义dω = dA / rr,即除以着色点x与光源采样点 x’ 距离的平方。

        于是根据图中二者的关系可将渲染方程改写如下。

        这样便成功从对 ωi 的积分转到了对光源面积 A 的积分,然后就可以利用蒙特卡洛的方法对光源进行采样从而计算直接光照的积分值,因为是对光源进行采样所以就不需要俄罗斯轮盘赌了(不涉及弹射)。对于间接光照,依然采用先前的方法进行光线方向的均匀采样。最终伪代码如下,分直接光照和间接光照两部分计算。

        计算直接光照的时候还需要判断光源与着色点之间是否有物体遮挡,该做法也很简单,只需从着色点 向光源采样点 x’ 发出一条检测光线判断是否与光源之外的物体相交即可,如图所示。

        伪代码修改如下。

        到这一步,路径追踪才真正完整了,路径追踪几乎可以达到100%真实感,如下图所示真实照片和路径追踪效果的对比,感受一下照片级真实(Photo-Realistic)。

3.2.5 遗留问题

        1.路径追踪对点光源很难处理。只能把点光源做成面积很小的面光源。

        2.路径追踪实现很困难。需要掌握的知识太多,比如物理量、微积分、概率、几何。

        

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1889689.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从0开始transformer代码理解(附带调试和个人原理理解)

代码来源 本次代码来源自github https://github.com/graykode/nlp-tutorial 里面的5.1 transformer代码 第一步 数据准备&#xff08;从main函数开始&#xff09; 首先这里是自定义了三句话&#xff0c;分别是给到encoder的输入和decoder的输入还有测试的输入 sentences […

使用python做飞机大战

代码地址: 点击跳转

【多媒体】Java实现MP4和MP3音视频播放器【JavaFX】【音视频播放】

在Java中播放音视频可以使用多种方案&#xff0c;最常见的是通过Swing组件JFrame和JLabel来嵌入JMF(Java Media Framework)或Xuggler。不过&#xff0c;JMF已经不再被推荐使用&#xff0c;而Xuggler是基于DirectX的&#xff0c;不适用于跨平台。而且上述方案都需要使用第三方库…

Spring Boot2.x教程:(四)Spring Boot2.6及之后版本整合Knife4j的问题

Spring Boot2.6及之后版本整合Knife4j的问题 1、概述2、问题出现原因及解决办法3、拓展3.1、为什么发生这种变化 4、总结 大家好&#xff0c;我是欧阳方超&#xff0c;可以扫描下方二维码关注我的公众号“欧阳方超”&#xff0c;后续内容将在公众号首发。 1、概述 今天在2.7…

66.WEB渗透测试-信息收集- WAF、框架组件识别(6)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;65.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;5&#xff09; 关于waf的一些识…

day62--若依框架(基础应用篇)

若依搭建 若依版本 官方 若依官方针对不同开发需求提供了多个版本的框架&#xff0c;每个版本都有其独特的特点和适用场景&#xff1a; 前后端混合版本&#xff1a;RuoYi结合了SpringBoot和Bootstrap的前端开发框架&#xff0c;适合快速构建传统的Web应用程序&#xff0c;其…

ByteTrack论文阅读笔记

目录 ByteTrack: Multi-Object Tracking by Associating Every Detection Box摘要INTRODUCTION — 简介BYTE算法BYTE算法用Python代码实现实验评测指标轻量模型的跟踪性能 总结SORT算法简介ByteTrack算法和SORT算法的区别 ByteTrack: Multi-Object Tracking by Associating Eve…

idm 支持断点续传吗 idm 断点续传如何使用 idm断点续传怎么解决 idm下载中断后无法继续下载

断点续传功能&#xff0c;让我再也不会惧怕下载大型文件。在断点续传的帮助下&#xff0c;用户可以随时暂停下载任务&#xff0c;并在空闲时继续之前的下载进程。下载文件不惧网络波动&#xff0c;断点续传让下载过程更稳定。有关 idm 支持断点续传吗&#xff0c;idm 断点续传如…

css---before和after伪元素

1.什么是伪元素 伪元素不是真正的页面元素&#xff0c;html没有对应的元素&#xff0c;但是其所有用法和表现行为与真正的页面元素一样&#xff0c;可以对其使用如页面元素一样的CSS样式&#xff0c;表面上看上去貌似是页面的某些元素来展现&#xff0c;实际上CSS样式展现的行…

京东e卡怎么用?

京东618过去后&#xff0c;就没有多大购物欲望了&#xff0c;最后导致我手里还有好几张200块钱面值的e卡没地方用 本来说送朋友&#xff0c;但是又感觉面值太小了 最后还是在收卡云上把提取出来了&#xff0c;主要回收价格不错&#xff0c;而且到账也快&#xff0c;很方便

TI电池电量计应用指导

前言&#xff1a; 电池电量计应用指导,来源:TI,因PDF有200页&#xff0c;在文尾附有目录&#xff1b;上传提示资源重复&#xff0c;请自行下载&#xff0c;找不到的可私信。 电池充电曲线&#xff0c;红色为电压&#xff0c;蓝色为电流 图2.10 匹配化学 ID 所需要的电压电流曲…

大模型补贴政策来了!!!

广州琶洲人工智能与数字经济试验区管理委员会 广州市海珠区科技工业商务和信息化局关于印发广州市海珠区建设人工智能大模型应用示范区实施细则的通知 各有关单位&#xff1a; 为进一步促进海珠区人工智能大模型产业发展&#xff0c;加快建设人工智能大模型应用示范区&#xf…

启动游戏提示缺少XAPOFX1_5.dll怎么处理?七个解决方法教你快速修复

xapofx1_5.dll是什么&#xff0c;打开软件或软件突然出现找不到xapofx1_5.dll文件&#xff0c;相信各位都很疑惑为什么会出现这个问题。今天我就教大家遇到这个问题怎么解决&#xff0c;和介绍xapofx1_5.dll文件全面分析以及xapofx1_5.dll多种解决方法&#xff01; 一、xapofx1…

页面替换菜单栏图标

图标素材库&#xff1a;https://www.iconfont.cn/?spma313x.collections_index.i3.2.51703a81hOhc8B 1、找到自己喜欢的图标下载svg 2、添加到icons中 3、在components中创建对应的vue页面添加对应图标svg中代码 4、在router中引入 5、在对应的菜单下使用图标

el-tree懒加载数据改变后不能实时刷新问题

简介 设置lazy后&#xff0c;加载数据通过load获取&#xff0c;如果外部搜索条件改变&#xff0c;数据源变动后&#xff0c;el-tree仍然是老数据不更新最新数据&#xff0c;因为el-tree加载后会缓存&#xff0c;需要主动设置data去更新最新数据 效果 源码 <!DOCTYPE html…

微信小程序云开发引入车牌识别踩坑

创造灵感 因为我写的是一个汽车轮胎商城小程序,要记录客户车牌信息,用到了车牌识别,小程序的插件服务里面有ORC插件支持,只需要把这个插件的车牌识别引进来就能用,这个插件每天有100次的免费识别,基本就够用了,下面把引入的踩坑过程记录一下.如果有需要汽车轮胎的也可以到我们…

softmax从零开始实现

softmax从零开始实现 代码结果 代码 import numpy as np import torch import torchvision import torchvision.transforms as transforms from torch.utils import data# H,W,C -> C,H,W mnist_train torchvision.datasets.FashionMNIST(root"./data", trainTr…

《石化技术 》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《石化技术 》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定学术期刊。 问&#xff1a;《石化技术 》级别&#xff1f; 答&#xff1a;国家级。主管单位&#xff1a;中国石油化工集团有限公司 主办单位&…

虚拟机下基于海思移植QT(一)——虚拟机下安装QT

0.参考资料 1.海思Hi3516DV300 移植Qt 运行并在HDMI显示器上显示 2.搭建海思3559A-Qt4.8.7Openssl开发环境 1.报错解决 通过下面命令查询 strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC_通过命令行没有解决&#xff1a; sudo apt install libc6-dev libc6参考解决…

内容监管与自由表达:Facebook的平衡之道

在当今数字化信息社会中&#xff0c;社交媒体平台不仅是人们交流和获取信息的主要渠道&#xff0c;也是自由表达的重要舞台。Facebook&#xff0c;作为全球最大的社交网络平台&#xff0c;连接了数十亿用户&#xff0c;形成了一个丰富多样的信息生态。然而&#xff0c;如何在维…