GAMES101课程学习笔记—Lec 14~16:Ray Tracing BRDF渲染方程全局光照路径追踪
Posted 清清!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GAMES101课程学习笔记—Lec 14~16:Ray Tracing BRDF渲染方程全局光照路径追踪相关的知识,希望对你有一定的参考价值。
GAMES101课程学习笔记—Lec 14(2)~16:Ray Tracing(2) BRDF、渲染方程、全局光照、路径追踪
- 0 引入——辐射度量学概述
- 1 相关概念
- 2 双向反射分布函数(Bidirectional ReflectanceDistribution Function,BRDF)
- 3 反射方程→渲染方程(The Reflection Equation→The Rendering Euqation)
- 4 深入理解渲染方程 Understanding the rendering equation
- 5 概率论回顾 Probability Review
- 6 蒙特卡洛积分 Monte Carlo Integration
- 7 路径追踪 Path Tracing
- 8 Some Side Notes
0 引入——辐射度量学概述
- 在之前讲Blinn-Phong着色模型时,会设置一个数当做光照强度,但是这个数真实的物理意义我们并不甚清楚,我们只是极大简化成一个数
Whitted风格的光线追踪不是一个真实的结果
所有的这些都会被辐射度量学解决,这也是路径追踪的基础
- 辐射度量学给出了一系列度量方法和单位去定义光照
它定义了光照在空间中的属性,这在物理上是完全正确的
同时闫老师提供了他学习新东西的方法:从探究为什么学,到这东西是什么,它具体是怎么运作的
1 相关概念
1.1 Radiant Energy and Flux (Power)
- Radiant energy:辐射能量,单位焦耳J,
Radiant Flux(Power):单位时间内辐射出的能量,可以表示光的亮度
- Flux也可以理解为单位时间内通过这个平面的光子的数量
- 知道了这两个概念我们可以定义出其他物理量
以下三个概念简述
Radiant Intensity——光源往四面八方都会辐射能量,我们要定义一个方向性的和能量相关的概念
Irradiance——在物体表面接受到的能量
Radiance——光线在传播中的能量
1.2 Radiant Intensity
- Radiant Intensity:在单位时间内,往每个立体角(Solid Angle)上辐射出的能量
- 那什么是立体角呢,我们先从平面角入手
平面角的定义是以弧长除以半径,并且此时圆的放大缩小并不影响这个角度,平面角最大为2π
扩展到三维,立体角的定义是面积除以半径的平方,根据积分可得立体角最大为4π
- 定义完立体角,我们接着定义单位立体角
用一块单位面积除以半径的平方
这块单位面积我们用球面坐标的θ和φ的变化来定义可以得到
单位立体角的积分可以得到是4π,印证之前的结论
- 现在回头看Intensity,我们定义一个均匀发光的点光源,积分全部的单位立体角上的Intensity得到能量,单位立体角上的Intensity也是能量除以4π
- 下面举一下生活中的例子
标着60w的LED灯,其实是功耗为11w,亮度相当于60w的白炽灯
我们也可以算它的Intensity,假设是均匀发光,用能量lumens除以面积4π得到单位立体角上的Intensity
1.3 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正确解释:
在最内部的单位球上, I r r a d i a n c e ( E ) = φ / 4 π Irradiance(E) = φ/4π Irradiance(E)=φ/4π,单位面积上接受到的能量就是 φ / 4 π φ/4π φ/4π,
而在外部的球面上, I r r a d i a n c e ( E ’ ) = φ / 4 π r 2 Irradiance(E’) = φ/4πr^2 Irradiance(E’)=φ/4πr2,,在单位面积上接受到的能量就是 φ / 4 π r 2 φ/4πr^2 φ/4πr2,所以就是r平方的衰减。
所以就可以知道,在这里衰减的并不是Radiant Intensity,而是Irradiance在衰减。
如果从球心以一个立体角画一个锥形,就可以知道,随着球面越来越大,立体角的大小是不变的,而立体角对应单位面积的大小却越来越大,
所以球面越大时,dA越大,Irradiance也就会越小。
1.4 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) 它在每个单位立体角、每个投影的面上有多少
也就是,某个单位面,往某个单位立体角方向上的发出的能量
1.5 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
2 双向反射分布函数(Bidirectional ReflectanceDistribution Function,BRDF)
我们之前说反射
如果从一个地方发出光线打到一个镜子,然后光线会反射到另一个方向去;如果打到漫反射物体,那么往四面八方都会去
我们需要有一个函数来描述这种性质:从某个方向进来,并且反射到某个方向去的能量是多少
反射在我们之前的理解中,是一道光线到达一个表面,然后反射到其他的方向去
这个过程其实也可以看作是从某一个方向来的光线,到达物体表面后,被物体表面所吸收,然后再由物体表面发射到其他方向去
这也就是用到了Radiance和Irradiance来解释反射
-
d
E
(
w
i
)
dE(w_i)
dE(wi)表示:从
w
i
w_i
wi方向射来的Radiance在到达反射点时,被吸收转化,然后得到的Irradiance
d L ( x , w r ) dL(x,w_r) dL(x,wr)则表示反射点向 w r w_r wr方向反射出去的Radiance - 我们知道反射点要吸收来自某一个方向的Radiance把它变成Irradiance,之后要反射到四面八方的立体角Radiance上
但是我们不知道反射到wr的方向上的Radiance会有多少能量 - 所以我们就为此定义一个函数,计算出:
考虑一个微小的面积 d A dA dA,从某一个微小的立体角 d w i dw_i dwi上接受得到到的Irradiance,会如何被分配到各个立体角上。
其实求得就是一个比例,是什么比例?
这个比例是
(对于任何一个立体角上发出去的 Radiance) / (单位面积 d A dA dA接收到的Irradiance)
这就是BRDF的定义
它会告诉我们如何把表面上收集到的能量以某一种比例放射到其他的方向上去
BRDF能表示从每个入射方向收集到的能量以某种比例反射到每个出射方向上的能量
即某个光线打到物体表面后,往不同方向反射的能量分布。
如果说是镜面反射,那么只有反射方向上会有能量,其他所有方向上都没有能量;如果是漫反射,这个进来的能量会被均等的分布到各个方向上
- 忽略推导部分,其实BRDF就是描述了物体和光线之间的相互作用
正是由于BRDF的这种概念,决定了物体不同的材质到底是怎么一回事,也就是BRDF定义了材质
3 反射方程→渲染方程(The Reflection Equation→The Rendering Euqation)
反射方程(The Reflection Equation)
- 从上面的分析可以得到, d L r ( w r ) dL_r(w_r) dLr(wr)是 从 w i w_i wi角度入射的能量 最后反射到 w r w_r wr方向上的能量。
- 而在反射的过程,我们并不是只对单一的,来自某一个方向的能量进行反射,而是要将来自四面八方的能量都收集起来,然后反射到某一个角度上。
- 所以要得到最终的反射效果,应该是:
通过BRDF计算出:每个方向接受的能量 它反射到 w r w_r wr方向上的能量是多少
然后把这些能量全部累加起来,得到的就是 w r w_r wr方向上反射的能量
可以用积分表示
(H的平方表示的积分面积为整个半球面,下面的整个表达式就是反射方程)
- 在考虑反射方程的时候,我们还要注意到:
反射点接受的能量(Irradiance)并不只是来自于光源,还会来自别的表面反射来的光(Irradiance)
从反射点反射出去的能量(Radiance)也并不只会反射到Camera或者人眼,还会作为Irradiance反射到其他的面上
所以反射方程的定义就成了一个递归的定义,也因此,光线反射的次数不同,得到的最终效果也就不会不同
但是我们目前先不考虑这些,把递归的思考先放在这里,做一个通用化
渲染方程(The Rendering Euqation)
- 渲染方程与反射方程相比,渲染方程只是多加了一个自己发光的能量。
因为我们在考虑物体表面对光进行反射的时候,没有考虑物体自己发光的情况,所以渲染方程就加上了物体自身发光的能量。
渲染效果 = 反射光 + 自身 发光,渲染方程如下:
(注意我们默认所有方向都是朝外的)
4 深入理解渲染方程 Understanding the rendering equation
我们对渲染方程进行加深理解
- 我们首先从反射方程来看,假设有一个点光源
它的反射光=自发光+入射光×BRDF×入射光与法线的夹角
- 如果有很多点光源,那么自然就是累加,把每一个点光源的照亮这个点的能量加起来
- 如果有面光源怎么办?面光源我们理解成点光源的集合,也就是进行积分
- 但是如果不只是光源,还有其他物体的反射来的光
我们就把其他物体的反射面当成光源
也可以说是从这一点往某个方向辐射出去的Radiance也是依赖着其他的点辐射出来的Radiance,也就是递归过程
- 当年渲染方程的论文配的效果图
4.1 全局光照 Global illumination
- 我们对方程进行简写,把 位置+角度 这两个变量用一个概括,变成u以及v,写成了积分的式子
继续把方程写成算子的形式
利用算子的运算性质(求逆以及泰勒展开)来解方程,解出L
- 于是渲染方程被拆解成以光的弹射次数为区分的很多项
把光线弹射的次数的项都加起来,也就是得到了全局光照
- 用渲染方程来理解光栅化,光栅化做的只有自发光以及直接光照
下面我们可以看一下加上不同光线弹射次数对应的效果图
- 直接光照
- 一次弹射的全局光照(直接光照+一次弹射)
- 两次弹射的全局光照
(注意灯此时是黑色的)
- 四次弹射的全局光照
(注意灯此时是亮起来了的,此时光才弹射出来,因为有些物体,光进去之后需要一定弹射次数才能出来)
- 八次与十六次,发现差别不大,也就是会逐渐收敛
5 概率论回顾 Probability Review
大学里大家都学过概率论,所以就简略写了
- 离散型随机变量及其分布
离散型随机变量的期望
连续型随机变量的概率密度函数(PDF)与期望
随机变量的函数
6 蒙特卡洛积分 Monte Carlo Integration
关于学习蒙特卡洛积分,我们首先也分三步走
- Why
蒙特卡洛积分方法是为了算那些计算起来比较困难的定积分(解析式很难写或者写不出),它提供了一种数值的方法可以直接算出值
- What&How
举个简易的例子,我们可以在定义域内随意取一个样本,然后得到对应的f(x)的值,那么整个函数的积分就是f(x)
我们也可以取多个样本,然后把它们的值均起来,整个函数的积分就是这个结果
蒙特卡洛积分正式的定义方式为,为了计算一个定积分,用一种pdf在定义域采样
于是这个定积分的值 可以用采样的值与pdf 近似成如下框中的形式
- 我们看一个用均匀分布采样的例子
- 蒙特卡洛积分可以算任何的积分,它只需要知道采样的pdf是多少就可以算积分
当然更多的采样会更准确
并且在哪里采样就在哪里积分
7 路径追踪 Path Tracing
7.1 回顾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是错的,渲染方程是对的
渲染方程的求解涉及到半球上积分的计算以及递归的执行
7.2 求解渲染方程 A Simple Monte Carlo Solution
我们考虑一个简单场景
这个场景有一个大的面光源,有一个着色点,有其他物体可能挡住光,还有观测方向
我们先计算这个点的直接光照
- 我们忽略发光项,这个着色点的最后被我们看到的光,就是四面八方来的光和BRDF作用之后反射到我们的观察方向上
这就是个半球上的积分,我们使用蒙特卡洛的方法来解它
- 我们考虑着色点为P点
先用简单的均匀采样的方法(半球的面积是2π,概率密度函数也就为1/2π)
- 于是我们可以用蒙特卡洛积分计算直接光照
- 用伪代码表示
先选N个方向,对于每个方向打光,如果打到了光源(这里是和推导逆向),就累加计算
直接光照好做,但是我们还要引入间接光照才能更真实
- 如图光源经过Q到P到眼睛
我们希望知道从Q到P有多少,又是从P看Q,其实也就相当于眼睛在P,看Q的直接光照
- 我们用简单直观的方法在伪代码中加上一段,看它有没有光线打到物体所在的Q,进行递归来求间接光照
但是这样行不通
7.2.1 问题一:数量问题→N=1
按照上面的方式做路径追踪不行,一个问题是因为光线的数目会爆炸
- 光线数目以指数的数量级上升
- 那么N为几的时候,指数才不会爆炸呢,那么只有N为1,即每个着色点只有一条光线
当然,我们也知道N为1是个误差很大的结果,怎么解决是后话,暂且搁置
到此为止,我们用N为1做蒙特卡洛积分,这也就是路径追踪
N不为1就是分布式光线追踪
之前说到N为1误差大,这没问题,因为这只是一个路径,我们可以在一个像素中可以有很多路径,这些所有的路径都会穿过这个像素
- 像素最后的颜色是什么要看这些路径的Radiance求平均
所以我们只要有足够多的Path就可以了
- 像素内取N个位置,对于每个位置,形成光线,计算着色
随机产生N个路径其实也是蒙特卡洛积分
7.2.2 问题二:递归问题→俄罗斯轮盘赌
- 第二个问题在于这个递归没有终止条件
- 但是在光线弹射的现实世界中,光线是不会停下来,因为限制次数会损失能量,比如下面三次和十七次弹射的对比图,明显有亮度差异
那我们应该怎么解决呢?我们引入俄罗斯轮盘赌的概念
- 俄罗斯轮盘赌也就是类似伯努利分布的概念
- 我们用类似算伯努利分布期望的方法来算能量
我们让算期望的结果还是 L o L_o Lo
也就是轮盘赌的期望依然是原来的能量结果
也就是 P × ? + ( 1 − P ) × ? ? = L o P×?+(1-P)×??=L_o P×?+(1−P)×??=Lo
我们巧妙的让
P的概率得到能量是 L o / P L_o/P Lo/P,1-P的概率得到的能量是0
此时刚好
- 我们总结到伪代码上去
最开始进行轮盘赌
然后在之后的代码里除以P
7.3 Sampling the Light
现在我们得到了一个正确的Path Tracing的方法
左边用较低的采样率,跑得快但是效果差
右边用高采样率,跑得慢但是效果好
但是效率不高,我们想要在低采样率下也效果好
- 问题出在哪里呢?
光源有时候有大的有小的
这样的话,之前的方法中,着色点往外是均匀采样,打光线出去的时候,很多光线都被浪费掉了,真正能打到光源的很少
我们不希望这种浪费的现象,是不是可以有其他的pdf采样
怎么样才是完全不浪费的采样呢?
- 如果我们可以直接在光源上采样
也就是采样样本直接分布在光源的表面上,那么所有光线都不会被浪费了 - 我们在光源上采样,光源本身有朝向的法线n’
光源和着色点连线,得到两个角,一个是和着色点法线的夹角θ,一个是和光源表面的法线夹角θ’ - 我们采样光源,光源理解成一个二维的框,在这个二维的平面上均匀采样,也就是pdf=1/A(假设光源面积是A,因为在面积上采样把pdf积分起来需要是1,所以pdf就要是1/A)
- 但是渲染方程可不是定义在光源上的,渲染方程的积分是定义在立体角上,定义在着色点的半球上的
蒙特卡洛积分要求积分和采样是在一个域上,我们现在是在光源的面积采样,在着色点半球的立体角积分,这样就不对了
为了继续使用渲染方程,我们要把渲染方程写成在光源上的积分
- 为了进行改写,我们只要需要知道 d w dw dw和 d A dA dA的关系就可以进行替换了
- d A dA dA是在光源上的一个小的表面, d w dw dw是这个小的表面对应到单位球上的立体角是多少
- 所以我们把
d
A
dA
dA转过来(乘以cos),此时除以到圆心的距离的平方就是立体角
d
w
dw
dw了(立体角的定义)
- 接下来我们重写渲染方程,
d
w
dw
dw换成
d
A
dA
dA
现在就变成了,在光源采样并且对光源积分了
并且因为是对光源的均匀采样,所以pdf是1/A
- 之前我们是盲目地在着色点上往各个方向打出去,打不打得到光源看运气,现在我们直接对光源采样
此时考虑着色的结果时,分为两部分
来自光源的贡献,直接采样光源
来自其他反射物的贡献,用俄罗斯轮盘赌来做
- 将上述逻辑写成伪代码的形式
- 我们对光源采样其实还有一个小问题,就是光源和物体之间可能还有遮挡
我们要判断一下是否遮挡
到此为止路径追踪就结束了
8 Some Side Notes
- 写对路径追踪不容易,通过学习可以理解更深
目前学的路径追踪可能比入门高一些,但是很现代
- 路径追踪是完全正确的
- 对Ray tracing进行总结
现在来说,Ray tracing代表光线传播方法的大集合:单向或者双向路径追踪,光子映射…
- 没覆盖到的话题:
让方向均匀分布在半球上,怎么做?
蒙特卡洛积分用什么pdf是比较好的?(重要性采样)
随机数有质量区分吗?
- 没覆盖到的话题:
我们可以采样光源,也可以采样半球,可以结合起来吗?(muliple imp. sampling)
为什么路径能量平均起来就是像素?要不要加权?
我们得到radiance,但是最后像素显示需要颜色,我们要做伽马矫正,怎么做?
路径追踪算入门嘛?算入门
以上是关于GAMES101课程学习笔记—Lec 14~16:Ray Tracing BRDF渲染方程全局光照路径追踪的主要内容,如果未能解决你的问题,请参考以下文章
计算机图形学学习笔记——Whitted-Style Ray Tracing(GAMES101作业5讲解)
UE4 Material 101学习笔记——23-29 水涟漪/水深/折射反射/Gerstner海浪/波光焦散/泡沫/FlowMap
UE4 Material 101学习笔记——30-37 植物叶片(透光/mask/面片隐藏/法线调整/AO/渐隐/世界空间色彩/随风舞动)