基本光线跟踪算法
光线定义
首先先要对光线定义
●光沿直线传播;
●不发生碰撞;
●是从光源到人眼的——对于第三个性质,我们在根据光路可逆性,会采取从人眼到光源的方法
光线追踪是从人的眼睛(摄像机)出发,向世界中投射光线
Ray Casting 光线投射
假设往虚拟的世界中看,眼前放了一个成像平面,成像平面被画成不同的像素格子
对于每一个像素,可以从相机连一条线,穿过这个像素,这样就可以打出一根光线,可以打到场景中
如果光线和场景的某一物体相交,那么交点和光源连线,看光源是否可见这个点(这个点在不在阴影里),如果可见,那么就形成一条有效的光路
那么就可以计算这条光路上的能量,进行着色
下面的例子中,假设眼睛是一个摄像机(即眼睛是一个点,一个位置,不考虑实际相机的处理)
对于场景中的物体,假设光打到它之后会发生完美的折射与反射
下图从眼睛开始,穿过成像平面的一个像素,投射一条光线(eye ray)这个光线会打到场景的某一个位置上,找到最近的交点(这一步其实就解决了深度测试的问题)
当发现了一个点之后,要考虑这个点会不会被照亮。从这点到光源连一条线(shadow ray)
如果可以连上就表示能被照亮(下图黑线箭头为法线)
有了法线,入射方向,出射方向,我们就可以做着色,写入像素的值,这时候可以用各种各样的着色模型比如之前的Blinn Phong
光线投射做了这么一件事,每一个像素投出去一个光线,和场景相交求的话求最近交点,最近交点和光源连线,判定是否可见,然后算着色,写回像素的值
递归(Whitted风格)光线追踪
光线投射的方法,还是只考虑光线弹射一次,但其实光线可以弹射很多次。
自光线投射开始
找到最近的点
假设球是玻璃球
会发生两种现象:反射和折射
在任意一个点,Whitted风格讲述的光线可以继续传播
着色的过程中也发生了一点变化
之前是光线投射到这个点之后,看这个点能不能被照亮,然后再计算它的着色,由于光线弹射次数多了,要在每一个弹射点都会计算着色的值(能量损失什么也要算)然后把它们都加回这个像素的值里面去
可以对光线类型进行分类
光线与物体相交
找到光线投射的最近交点
光线与隐式表面相交
数学上的光线定义
光线定义也就是一条射线,有一个起点,有一个方向,有这两个量就可以定义一条光线光线上的任何一个点都可以用 t 为自变量的函数表示
为了说明光线与曲面的交点从光线与球求交的情况开始切入,交点即这个点又在球上又在光线上方程于是可以建立起来了
根据解的情况可以得到位置关系
拓展到一般性的隐式表面
光线与显式表面求交
在几何上,通过这个办法也可以判断一个点在不在物体内(点如果在封闭形状内,向外打一条光线,得到的交点数量一定是奇数)
话题回到光线与三角形求交
在下图的小奶牛中,判断光线是否与它相交
最简单的做法就是把它的三角形面挨个判断一遍(每个三角形面都会有0个或者1个交点)
很直观但是很慢
怎么样做三角形和光线的交点呢?
三角形肯定在一个平面内,所以问题可以被分成两部分
●光线是否和平面有交点
●这个交点在不在三角形内部
平面的定义采用点法式的定义方式用一个平面上的点与平面上的法线,利用点乘为0的方式建立平面方程
把光线方程带入平面方程,解出来光线与平面的交点再之后可以判断在不在三角形内部
将原有的两个步骤合成一个步骤
左边是光线上的点,右边是用重心坐标表示的三角形内的点
解法如下图
解出来之后要判断是否合理,首先 t 得是正的,并且b1 b2 b3都是非负的
轴对齐包围盒(AABB)的求交
与每一个三角形求交,可以找到最近的交点
但是 计算次数 = 像素数×三角形数×弹射数
在大场景,复杂场景中这样计算量过于庞大,效率也很低
所以要对这个过程进行改进加速,方法之一是包围盒(类似于碰撞体积?)
将一个复杂的物体,用简单的形状围起来,保证物体一定在这个简单的形状之内如果光线连包围盒都碰不到,那肯定碰不到包围盒里的物体
建立AABB(轴对齐包围盒)
长方体是三个不同对面(无限大 )的交集
轴对齐,也就是长方体的任何一个轴都是沿着坐标轴的
下面来求光线于包围的交点
降低思维复杂度先从二维的角度(由不同的两对对面形成)考虑,由两个对面形成的交集
三维可以同理得到
对于给定的一个光线
分别求出它与竖直和水平面的交点(此时t可能会有正负)取min里的max,max里的min,于是得到了进入和出去包围盒的 t 的值
判断进入与离开的时机
只有所有光线都进入了三组对面,才能说光线进入了这个盒子只要光线离开任意一对对面,光线就离开了这个盒子我们对三组对面都计算一次 t(最大最小时间)取min中的max为最后进入时间,max中的min为最早出去的时间进入时间小于离开时间时,也就代表光线在它们之间是在盒子里的
一直都在考虑的是光线为直线情况下,也并没有考虑负值
但光线不是直线,是射线所以有交点的情况下,需要对 t 进行检查盒子在光线背后——出去时间是负数光线起点在盒子内部——出去时间是负数且进入为正数
总结,光线和AABB当且仅当进入时间小于离开时间(且离开时间为非负数)为正数,此时才会有交点
iff——>(if and only if)
为什么要用AABB
轴对齐情况下,可以在求t的时候只用某一轴的信息,不用整个坐标
计算量较少
使用轴对齐包围盒加速光线追踪
如果场景非常复杂,我们会先找到包围盒,然后再根据包围盒的情况进行对物体的求交找到包围盒的过程是空间划分的过程
均匀空间划分
找到场景的包围盒
做光线追踪前,对场景进行预处理,将包围盒分成格子
判断与物体(表面)相交的格子
得到可能含有物体的格子接下来做光线追踪的过程中,只要判断光线交到的是不是有物体的格子,不是的话直接跳过,是的话再对盒子里的物体求交(假设光线与物体求交很慢,与盒子求交很快)
光线沿着右上角打过去,不需要判断每个格子是否与光线相交,只需要考虑光线的方向,(例如光线往右上打,则光线一定是与右侧和上边的格子相交)判断是否有交点
这里的概念是之前没有提的话题,如何光栅化一条线
加速,就是多做光线与盒子求交点,少做光线与物体求交
加速效果怎么?假设将整个空间划分成1X1的格子,那么就没有加速效果
格子太过于密集,效率也不高
需要找到一个中间值,大概得出的划分成,场景中物体数目的27倍的格子比较好
格子的划分方法在大量均匀分布的物体上比较有效
空间划分
在格子法中,空间划分的都是大小相同的格子,然而有些空旷的地方不需要这样,太浪费了,我们想在没物体的地方用大盒子,有物体的地方用密集的盒子这也就引出了空间划分的方法
左一是八叉树划分,先把三维空间切成八份(二维的话如图是四份),对于每一个子节点,再切成四份,以此类推
如何停止:我们可以定个类似这样的规则,比如二维的情况,切成四块时三块都没物体,就不在往下切 ,其思想也就是划分到一定程度没有物体就不再继续
在二维这种划分方法是四叉树,三维是八叉树,那么维度更高,就是2的n次方叉树,这样并不好,维度更高会越来越复杂
为了解决这个问题,能让空间得到划分并且和维度无关,发明了KD树
KD树和八叉树的划分方法几乎完全相同,只不过它每次沿着某一个轴看开,并且只砍一刀,永远这么做
空间被划分成类似二叉树的结果,每次节点的划分底下都只有两个子节点
划分时为了均匀起见,(二维为xy)xyz依次砍
还有很多方法,比如BSP树,是一种对空间二分的划分方法,它每次选一个方向砍开,它和KD树的区别是它不是横平竖直地砍,而且它会有越高维越不好计算的问题(砍开二维用线,砍开三维用面,维度越高越复杂)
KD树实例
首先要明确得是,空间划分方法是在光线追踪之前,先把空间加速结构划分好,再进行光线追踪‘
下图为示意图,只分了右下,实际是所有都要划分
在中间节点ABCD中,只需要记录好被划分成什么样得盒子(子节点)
在叶子节点,也就是最后决定不再划分得格子处储存节点。
建立数据结构来存储KD-Trees
对任意一个节点,都应该知道当前是沿着哪一个轴划分。
划分在哪里可以随便定义
对中间节点来说,一定有子节点,且一定是两个字节点
实际得物体和三角形,只存在叶子节点上
KD-Trees结构,如何加速光线追踪
先将整体划分成下图
最先考虑最大的包围盒A,发现有交点,那么对于左右子节点可能有交集
之后便会发现,和包围盒1,有交点
假设它为叶子节点,继续观察,会发现右边也有交点
以此类推判断2 然后判断C
然后判断3,发现3是叶子节点,在3中与物体求交,找到交点
KD-Trees会产生的一些问题
给出一个节点的包围盒,我们要知道它和哪些三角形有交集,这是很难的,不太好写
一个物体和很多包围盒都有交集的话,它可能会存在很多个叶子节点中
物体划分&BVH
不从空间划分,从物体开始划分,这种划分形成的加速结构也就是所谓的BVH
先看整体BVH大体如何进行,之后再仔细讲明如何划分
最开始也有一个盒子包围场景作为根节点
把这些物体,分成两部分。再重新给予分开后物体新的包围盒22222222222222222230
以蓝色盒子为例,继续划分再重新分别给予新的包围盒,划分到比较少的三角形,比如5个三角形左右便可以停止
BVH的特性是,一个物体可以指存在在一个节点里,并且不用算三角形和包围盒求交了但是BVH的划分并没有划分开,包围盒可能会相交,不过没什么问题,我们做到尽可能重叠少就好,这也是当今一个研究的方向下图进行了总结
关于怎么划分一个节点,有很多方法比如选一个最长的轴划分或者取中间的物体(第n/2个三角形)(可以采用快速划分算法)主要是为了保证树的平衡
关于BVH的存储结构也做一个总结,只有子节点存物体
如何加速光线追踪和KD树其实差不多,到子节点测物体
一个是对空间的划分,一个是对物体的划分,以下是总结
辐射度量学概述
Blinn-Phong着色模型时,会设置一个数当做光照强度,但是这个数真实的物理意义我们并不甚清楚,我们只是极大简化成一个数Whitted风格的光线追踪不是一个真实的结果所有的这些都会被辐射度量学解决,这也是路径追踪的基础
这里的辐射度量也在入门精要PBR章节中提及到。
辐射度量学表示如何去描述光照,给出了一系列度量方法和单位去定义光照
定义了光照在空间中的属性,这在物理上是完全正确的
P.S.如何去学习:从探究为什么学,到这东西是什么,它具体是怎么运作的
Radiant Energy and Flux (Power)
Radiant energy:辐射能量,单位焦耳J,Radiant Flux(Power):单位时间内辐射出的能量,可以表示光的亮度
lumen(流明)定义光源亮度
Flux也可以理解为单位时间内通过这个平面的光子的数量
通过前两个物理量定义其他物理量
Radiant Intensity——光源往四面八方都会辐射能量,我们要定义一个方向性的和能量相关的概念Irradiance——在物体表面接受到的能量 Radiance——光线在传播中的能量
Radiant Intensity
Radiant Intensity:在单位时间内,往每个立体角(Solid Angle)上辐射出的能量
什么是立体角?
从平面角入手,平面角的定义是以弧长除以半径,并且此时圆的放大缩小并不影响这个角度,平面角最大为2π扩展到三维,立体角的定义是面积除以半径的平方,根据积分可得立体角最大为4π
定义完立体角,我们接着定义单位立体角用一块单位面积除以半径的平方这块单位面积我们用球面坐标的θ和φ的变化来定义可以得到
近似的我们认为它是个长方形,其中由d\theta决定的这一边的弧长=rd\theta (弧度的定义就是其所对的单位圆的弧的长度)
而另一边则要求其所围圆的半径,也即图中以红色线为半径的水平圆,则其半径r_\varphi =rsin\theta
单位立体角的积分可以得到是4π,印证之前的结论
现在回头看Intensity,我们定义一个均匀发光的点光源,积分全部的单位立体角上的Intensity得到能量,单位立体角上的Intensity也是能量除以4π
标着60w的LED灯,其实是功耗为11w,亮度相当于60w的白炽灯
我们也可以算它的Intensity,假设是均匀发光,用能量lumens除以面积4π得到单位立体角上的Intensity
Irradiance
Irradiance 定义:在单位时间内,每个单位面积上接受到的光照的能量
即power per unit area
做一下对比,之前的Radiant Intensity是 power per unit solid angle
注:这个单位面积必须要和光线垂直,如果不垂直的话要把面积投影到垂直的方向上(图中没有写cos,暂时就一个dA)
类似之前的Biling - Phong里的内容
左图:单位面积和光线垂直,所以直接用Irradiance的计算式即可
中图:面积与光线不垂直,其投影只能接受到三根、一半的光线,所以要×1/2
右图:更普遍的情况,当单位面积与光线不垂直时,要乘cos将其投影到垂直的方向上去。
上面的Lambert’s余弦定理就解释了地球为什么会出现四季变换
当北半球是夏天时,太阳光直射北半球,北半球的Irradiance更多,也就更热;而当北半球是冬天时,光线与地球的表面有一定的夹角,Irradiance减少,所以冬天就更冷。
之前提到过,我们是假设能量集中在一个球壳上,随着球壳的增大,光的强度会有一个r平方的衰减;
现在可以用Irradiance正确解释:
在最内部的单位球上,Irradiance(E)=φ/4π,单位面积上接受到的能量就是φ/4π,
而在外部的球面上, Irradiance(E’) = φ/4πr^2,在单位面积上接受到的能量就是 φ/4πr ^2
所以就是r平方的衰减。
所以就可以知道,在这里衰减的并不是Radiant Intensity,而是Irradiance在衰减。
如果从球心以一个立体角画一个锥形,就可以知道,随着球面越来越大,立体角的大小是不变的,而立体角对应单位面积的大小却越来越大,
所以球面越大时,dA越大,Irradiance也就会越小。
Radiance
Radiance是描述 环境中 光的分布 的 基本场量(fundamental field quantity)
它主要用来准确描述光线的一些属性
准确的光线追踪与radiance关系非常大,渲染就是在计算radiance
Radiance定义:
英文定义:The radiance (luminance) is the power emitted, reflected, transmitted or received by a surface, per unit solid angle, per projected unit area.
定义:Radiant Flux(Power) 它在每个单位立体角、每个投影的面上有多少
也就是,某个单位面,往某个单位立体角方向上的发出的能量
Radiance&Irradiance&Intensity之间的联系与区别
我们把这几个概念进行一定区分和总结
Radiance : Irradiance per solid angle
按照放射能量(Radiance)的解释:
Radiance表示 单位面积dA 把它接受到的能量 朝w的方向辐射出的能量。
反过来按照吸收能量(Irradiance)的解释:
从w方向发射来的Radiance 到单位面积dA上 ,所有方向累计,单位面积dA一共接受得到的能量即 Irradiance
也就是 Irradiance 在w这个方向上的分量,就是Radiance
Radiance: Radiant Intensity per projected unit area
●Intensity代表的是所有面积会向某个单位立体角的方向上辐射出的能量,
●Radiance就代表这个Intensity在某个单位面积dA上的投影/分量
Radiance和Irradiance的区别和联系在图形学上用的很多,我们再总结一下
●Radiance是某个单位面向某个单位立体角辐射出去的能量
●Irradiance是某个单位面积上接受到来自四面八方的能量
把半球面上的所有Radiance积分起来得到的就是Irradiance
双向反射分布函数(Bidirectional ReflectanceDistribution Function,BRDF)
我们之前说反射
如果从一个地方发出光线打到一个镜子,然后光线会反射到另一个方向去;如果打到漫反射物体,那么往四面八方都会去
我们需要有一个函数来描述这种性质:从某个方向进来,并且反射到某个方向去的能量是多少
反射在我们之前的理解中,是一道光线到达一个表面,然后反射到其他的方向去
这个过程其实也可以看作是从某一个方向来的光线,到达物体表面后,被物体表面所吸收,然后再由物体表面发射到其他方向去
这也就是用到了Radiance和Irradiance来解释反射
dE(w i)表示:从w i方向射来的Radiance在到达反射点时,被吸收转化,然后得到的Irradiance
dL(x,w r )则表示反射点向w r方向反射出去的Radiance
●我们知道反射点要吸收来自某一个方向的Radiance把它变成Irradiance,之后要反射到四面八方的立体角Radiance上
但是我们不知道反射到wr的方向上的Radiance会有多少能量
●所以我们就为此定义一个函数,计算出:
考虑一个微小的面积d A dAdA,从某一个微小的立体角dw i上接受得到到的Irradiance,会如何被分配到各 个立体角上。
其实求得就是一个比例,是什么比例?
这个比例是(对于任何一个立体角上发出去的 Radiance) / (单位面积d A dAdA接收到的Irradiance)
这就是BRDF的定义
●它会告诉我们如何把表面上收集到的能量以某一种比例放射到其他的方向上去
BRDF能表示从每个入射方向收集到的能量以某种比例反射到每个出射方向上的能量
即某个光线打到物体表面后,往不同方向反射的能量分布。
如果说是镜面反射,那么只有反射方向上会有能量,其他所有方向上都没有能量;如果是漫反射,这个进来的能量会被均等的分布到各个方向上
忽略推导部分,其实BRDF就是描述了物体和光线之间的相互作用
正是由于BRDF的这种概念,决定了物体不同的材质到底是怎么一回事,也就是BRDF定义了材质
反射方程→渲染方程(The Reflection Equation→The Rendering Euqation)
反射方程(The Reflection Equation)
●从上面的分析可以得到,dL r (w r )是 从w i角度入射的能量 最后反射到wr 方向上的能量。
●而在反射的过程,我们并不是只对单一的,来自某一个方向的能量进行反射,而是要将来自四面八方的能量都收集起来,然后反射到某一个角度上。
●所以要得到最终的反射效果,应该是:通过BRDF计算出:每个方向接受的能量 它反射到w r方向上的能量是多少然后把这些能量全部累加起来,得到的就是w r 方向上反射的能量
●可以用积分表示(H的平方表示的积分面积为整个半球面,下面的整个表达式就是反射方程)
在考虑反射方程的时候,我们还要注意到:
●反射点接受的能量(Irradiance)并不只是来自于光源,还会来自别的表面反射来的光(Irradiance)
●从反射点反射出去的能量(Radiance)也并不只会反射到Camera或者人眼,还会作为Irradiance反射到其他的面上
●所以反射方程的定义就成了一个递归的定义,也因此,光线反射的次数不同,得到的最终效果也就不会不同
但是我们目前先不考虑这些,把递归的思考先放在这里,做一个通用化
渲染方程(The Rendering Euqation)
●渲染方程与反射方程相比,渲染方程只是多加了一个自己发光的能量。
●因为我们在考虑物体表面对光进行反射的时候,没有考虑物体自己发光的情况,所以渲染方程就加上了物体自身发光的能量。
●渲染效果 = 反射光 + 自身 发光,渲染方程如下:
(注意我们默认所有方向都是朝外的)
深入理解渲染方程 Understanding the rendering equation
我们对渲染方程进行加深理解
●首先从反射方程来看,假设有一个点光源
它的反射光=自发光+入射光×BRDF×入射光与法线的夹角
如果有很多点光源,那么自然就是累
加,把每一个点光源的照亮这个点的能量加起来
如果有面光源怎么办?面光源我们理解成点光源的集合,也就是进行积分
但是如果不只是光源,还有其他物体的反射来的光
我们就把其他物体的反射面当成光源
也可以说是从这一点往某个方向辐射出去的Radiance也是依赖着其他的点辐射出来的Radiance,也就是递归过程
当年渲染方程的论文配的效果图
全局光照 Global illumination
我们对方程进行简写,把 位置+角度 这两个变量用一个概括,变成u以及v,写成了积分的式子
继续把方程写成算子的形式
利用算子的运算性质(求逆以及泰勒展开)来解方程,解出L
于是渲染方程被拆解成以光的弹射次数为区分的很多项
把光线弹射的次数的项都加起来,也就是得到了全局光照
用渲染方程来理解光栅化,光栅化做的只有自发光以及直接光照
可以看一下加上不同光线弹射次数对应的效果图
●直接光照
●一次弹射的全局光照(直接光照+一次弹射)
●两次弹射的全局光照
(注意灯此时是黑色的)
●四次弹射的全局光照
(注意灯此时是亮起来了的,此时光才弹射出来,因为有些物体,光进去之后需要一定弹射次数才能出来)
●八次与十六次,发现差别不大,也就是会逐渐收敛
概率论回顾 Probability Review
大学里大家都学过概率论,所以就简略写了(我没学!)
离散型随机变量及其分布
离散型随机变量的期望
连续型随机变量的概率密度函数(PDF)与期望
随机变量的函数
蒙特卡洛积分 Monte Carlo Integration
关于学习蒙特卡洛积分,首先也分三步走
●Why
蒙特卡洛积分方法是为了算那些计算起来比较困难的定积分(解析式很难写或者写不出),它提供了一种数值的方法可以直接算出值
●What&How
举个简易的例子,我们可以在定义域内随意取一个样本,然后得到对应的f(x)的值,那么整个函数的积分就是f(x)
我们也可以取多个样本,然后把它们的值均起来,整个函数的积分就是这个结果
蒙特卡洛积分正式的定义方式为,为了计算一个定积分,用一种pdf在定义域采样
于是这个定积分的值 可以用采样的值与pdf 近似成如下框中的形式
●我们看一个用均匀分布采样的例子
蒙特卡洛积分可以算任何的积分,它只需要知道采样的pdf是多少就可以算积分
当然更多的采样会更准确
并且在哪里采样就在哪里积分
路径追踪 Path Tracing
回顾Whitted-Style Ray Tracing的问题
讲完了蒙特卡洛积分,我们就有了足够的知识储备来做路径追踪
●我们已经学过了Whitted-Style Ray Tracing
它会在镜面进行反射,并在漫反射表面停止
但是这样是不太对的,我们可以用Path Tracing的方法做出更好的效果
●Whitted-Style Ray Tracing无法做Glossy的材质,不能说光线打到Glossy的材质上也沿着Specular的方向走
(典型模型 The Utah teapot)
●Whitted-Style Ray Tracing不考虑漫反射的效果,但是实际上漫反射表面和漫反射表面之间还是会有作用的,比如color bleeding
下图的直接光照与全局光照的对比可以看出效果
(典型模型 The Cornell box)
●Whitted-Style Ray Tracing是错的,渲染方程是对的
渲染方程的求解涉及到半球上积分的计算以及递归的执行
求解渲染方程 A Simple Monte Carlo Solution
我们考虑一个简单场景
这个场景有一个大的面光源,有一个着色点,有其他物体可能挡住光,还有观测方向
我们先计算这个点的直接光照
我们忽略发光项,这个着色点的最后被我们看到的光,就是四面八方来的光和BRDF作用之后反射到我们的观察方向上
这就是个半球上的积分,我们使用蒙特卡洛的方法来解它
我们考虑着色点为P点
先用简单的均匀采样的方法(半球的面积是2π,概率密度函数也就为1/2π)
于是我们可以用蒙特卡洛积分计算直接光照
用伪代码表示
先选N个方向,对于每个方向打光,如果打到了光源(这里是和推导逆向),就累加计算
直接光照好做,但是我们还要引入间接光照才能更真实
●如图光源经过Q到P到眼睛
我们希望知道从Q到P有多少,又是从P看Q,其实也就相当于眼睛在P,看Q的直接光照
我们用简单直观的方法在伪代码中加上一段,看它有没有光线打到物体所在的Q,进行递归来求间接光照
但是这样行不通
问题一:数量问题→N=1
按照上面的方式做路径追踪不行,一个问题是因为光线的数目会爆炸
●光线数目以指数的数量级上升
那么N为几的时候,指数才不会爆炸呢,那么只有N为1,即每个着色点只有一条光线
当然,我们也知道N为1是个误差很大的结果,怎么解决是后话,暂且搁置
到此为止,我们用N为1做蒙特卡洛积分,这也就是路径追踪
N不为1就是分布式光线追踪
之前说到N为1误差大,这没问题,因为这只是一个路径,我们可以在一个像素中可以有很多路径,这些所有的路径都会穿过这个像素
●像素最后的颜色是什么要看这些路径的Radiance求平均
所以我们只要有足够多的Path就可以
像素内取N个位置,对于每个位置,形成光线,计算着色
随机产生N个路径其实也是蒙特卡洛积分
问题二:递归问题→俄罗斯轮盘赌
第二个问题在于这个递归没有终止条件
但是在光线弹射的现实世界中,光线是不会停下来,因为限制次数会损失能量,比如下面三次和十七次弹射的对比图,明显有亮度差异
那我们应该怎么解决呢?我们引入俄罗斯轮盘赌的概念
俄罗斯轮盘赌也就是类似伯努利分布的概念
我们用类似算伯努利分布期望的方法来算能量
我们让算期望的结果还是L o也就是轮盘赌的期望依然是原来的能量结果
也就是P×?+(1−P)×??=L o
我们巧妙的让
P的概率得到能量是L o/P,1-P的概率得到的能量是0
此时刚好
我们总结到伪代码上去
最开始进行轮盘赌
然后在之后的代码里除以P
Sampling the Light
现在我们得到了一个正确的Path Tracing的方法
左边用较低的采样率,跑得快但是效果差
右边用高采样率,跑得慢但是效果好
但是效率不高,我们想要在低采样率下也效果好
问题出在哪里呢?
光源有时候有大的有小的
这样的话,之前的方法中,着色点往外是均匀采样,打光线出去的时候,很多光线都被浪费掉了,真正能打到光源的很少
我们不希望这种浪费的现象,是不是可以有其他的pdf采样
怎么样才是完全不浪费的采样呢?
●如果我们可以直接在光源上采样
也就是采样样本直接分布在光源的表面上,那么所有光线都不会被浪费了
●我们在光源上采样,光源本身有朝向的法线n’
光源和着色点连线,得到两个角,一个是和着色点法线的夹角θ,一个是和光源表面的法线夹角θ’
●我们采样光源,光源理解成一个二维的框,在这个二维的平面上均匀采样,也就是pdf=1/A(假设光源面积是A,因为在面积上采样把pdf积分起来需要是1,所以pdf就要是1/A)
●但是渲染方程可不是定义在光源上的,渲染方程的积分是定义在立体角上,定义在着色点的半球上的
蒙特卡洛积分要求积分和采样是在一个域上,我们现在是在光源的面积采样,在着色点半球的立体角积分, 这 样就不对了
为了继续使用渲染方程,我们要把渲染方程写成在光源上的积分
●为了进行改写,我们只要需要知道dw和dA的关系就可以进行替换了
●dA是在光源上的一个小的表面,dw是这个小的表面对应到单位球上的立体角是多少
●所以我们把dA转过来(乘以cos),此时除以到圆心的距离的平方就是立体角dw了(立体角的定义)
●接下来我们重写渲染方程,dw换成dA
现在就变成了,在光源采样并且对光源积分了
并且因为是对光源的均匀采样,所以pdf是1/A
●之前我们是盲目地在着色点上往各个方向打出去,打不打得到光源看运气,现在我们直接对光源采样
此时考虑着色的结果时,分为两部分
来自光源的贡献,直接采样光源
来自其他反射物的贡献,用俄罗斯轮盘赌来做
将上述逻辑写成伪代码的形式
我们对光源采样其实还有一个小问题,就是光源和物体之间可能还有遮挡
我们要判断一下是否遮挡
到此为止路径追踪就结束了
Some Side Notes
写对路径追踪不容易,通过学习可以理解更深
目前学的路径追踪可能比入门高一些,但是很现代
路径追踪是完全正确的
对Ray tracing进行总结
现在来说,Ray tracing代表光线传播方法的大集合:单向或者双向路径追踪,光子映射…
没覆盖到的话题:
让方向均匀分布在半球上,怎么做?
蒙特卡洛积分用什么pdf是比较好的?(重要性采样)
随机数有质量区分吗?
没覆盖到的话题:
我们可以采样光源,也可以采样半球,可以结合起来吗?(muliple imp. sampling)
为什么路径能量平均起来就是像素?要不要加权?
我们得到radiance,但是最后像素显示需要颜色,我们要做伽马矫正,怎么做?
路径追踪算入门嘛?算入门