目录
0. 阴影:Shadow Mapping(从光栅化角度实现)
1.1 Recursive (Whitted-Style) Ray Tracing:模拟光不断弹射的过程
1.2 光线与表面求交 Ray-Surface Intersection
2.1 Bounding Volumes:AABB(轴对齐包围盒)
⭐2.2.1 判断光线是否与AABB相交:取进入时间最大值与离开时间最小是的交集
2.2.1 Oct-Tree、KD-Tree、BSP-Tree
2.3 物体划分:Object Partitions & Bounding Volume Hierarchy(BVH)
3.1 Radiant Energy & Flux(Power)
3.1.2 Radiant Flux:Lumen(流明)、功率
3.2 Radiant Intensity:每立体角发射的光强度
3.3.1 Lamber's Cosint Law:表面接受的能量只与垂直方向有关
3.4 Radiance:每单位立体角、每单位表面 接受、发射多少能量(描述光线)
3.4.1 Incident Radiance:每单位立体角到达表面的Irradiance
3.4.2 Exiting Radiance:每单位面积离开表面发射的Intensity
⭐3.5 Bidirectional Reflectance Distribution Function (BRDF):描述光从某个方向入射进来并且沿某方向反射出去的能量
3.5.2 渲染方程The Rendering Equation:反射方程+自身发光项
⭐3.5.3 全局光照:对反射方程的理解—直接光照+间接关照
4.1 蒙特卡洛积分:求一个复杂函数的定积分—解析解-->数值解
0. 阴影:Shadow Mapping(从光栅化角度实现)
思想:
- 一个可见点,你的视线可以看到,光源也可以看到
- 一个不可见点(阴影),你的视线可以看到,光源看不到
经典的Shadow Mapping 只能处理点光源的情形(硬阴影,边界非黑即白)
1.从光源出发,看向各个像素点,记录各个点的深度
2.从相机出发,从看到的点投影回光源,记录一个深度,若此点可见,则两次深度影响同
3.从相机出发,从看到的点投影回光源,记录一个深度,发现深度与从光源出发的深度不同,则为阴影
如果一个物体有软阴影,那么它的光源一定是有大小的。
硬阴影与软阴影的区别与原理,即本影(Umbra)和半影(Penumbra)的区别。
由此,shadow maps存在着一些问题:
⭐1.光线追踪:光路(线)的可逆性、光的折射、着色贡献度
1.0 Why Ray Tracing?光栅化的局限性
光栅化的局限性:
- 无法处理光线多次弹射的情况,即全局光照
- 光栅化虽快,但质量相对较低
1.1 Recursive (Whitted-Style) Ray Tracing:模拟光不断弹射的过程
引用课上闫老师的原话做一个精炼:
- 这是一个玻璃球,从视线发出的光线,会发生两种情况:折射与反射
- 着色发生了变化:原本只关注该点能否被光源照亮,只计算一次;Whitted-Style是考虑如果光源能够照亮任何一个可以发生弹射的点,就都把他们着色的值加到像素的值上去。
- 考虑光的能量损失。
计算光在不同次数下的折射的各个光路结果累加到一个像素中去。
在每一个弹射的点,都会计算其着色的值。最后都会被累加到视线穿过的像素点。
1.2 光线与表面求交 Ray-Surface Intersection
1.2.1 光线方程:r(t) = o + td
1.2.2 光线与球体求交:
1.2.3 光线与隐式表面求交:
⭐1.2.4 光线与三角形网格求交:两种方法
- 分解:先求光线与表面交点,再判断交点是否在三角形内
- 平面法线与平面内一点确定平面方程,与光线方程相等
- Möller Trumbore Algorithm:重心坐标,直接判断三角形与光线相交,克莱姆法则
⭐2. 光线追踪加速:
最基本的光线追踪会与场景中所有的三角形面求交,并且要计算每一个像素的值,Very Slow!
2.1 Bounding Volumes:AABB(轴对齐包围盒)
与x,y,z轴平行的三个面,故称轴对齐。
⭐2.2.1 判断光线是否与AABB相交:取进入时间最大值与离开时间最小是的交集
- 当光线穿过所有轴对齐面,即为进入AABB
- 当光线只要离开其中一个面,即离开AABB
- 当光线进入Box时间小于离开Box时间,即光源就在Box内部
这里考虑如下前提:光线是射线!,与集中特殊几种情况:
- :Box在光源之后,即光线与Box无交点!
- && :光源在Box内部,有交点!
总之,当且仅当: && ,光线与Box才有交点!
那为什么要用轴对称这一性质呢?原因很简单,免去了计算不平行与轴平面的法线的麻烦!
2.2 空间划分
2.2.1 Oct-Tree、KD-Tree、BSP-Tree
Oct-Tree:类似于切豆腐,三维物体切三刀,分为八块;二维物体切两刀,分为四块;以此类推。
如何切?比如在二维空间中切两刀(多了4块),发现这部分切完之后有三块都是空的,那就没必要继续切下去了。当然这只是一个直观理解上的例子,实际上什么时候停下来取决于具体约束,比如这部分有多少数量的物体即可停下,或者当这个格子是空的时候为止。
但随着维度增加,切的空间称指数级上升。
KD-Tree:每次沿着某一个水平或垂直轴(xyz)划分,为二分
⭐2.2.2 KD-Tree的光线求交判断过程:
但
- 如何判断三角形与AABB有交点是一件很难的事,所以KD-Tree逐渐减少了使用。
- 一个物体有可能出现在多个叶子节点中,也就是多个格子里。
2.3 物体划分:Object Partitions & Bounding Volume Hierarchy(BVH)
把物体分为两堆,重新计算包围盒
快速选择算法:快速选择算法 - Salty_Fish - 博客园 (cnblogs.com)
⭐3.辐射度量学(Radiometry)
3.0 Motivation
光的强度 Intensity?etc...
给光的各方面物理意义一个精确的定义!
3.1 Radiant Energy & Flux(Power)
3.1.1 Radiant Energy:能量
3.1.2 Radiant Flux:Lumen(流明)、功率
3.2 Radiant Intensity:每立体角发射的光强度
3.3 Irradiance:每单位表面接受多少能量
3.3.1 Lamber's Cosint Law:表面接受的能量只与垂直方向有关
3.4 Radiance:每单位立体角、每单位表面 接受、发射多少能量(描述光线)
3.4.1 Incident Radiance:每单位立体角到达表面的Irradiance
3.4.2 Exiting Radiance:每单位面积离开表面发射的Intensity
Irrandiance与Radiance的联系与区别: 积分的关系,单位的不同
⭐3.5 Bidirectional Reflectance Distribution Function (BRDF):描述光从某个方向入射进来并且沿某方向反射出去的能量
一个光从某个方向入射进来,会向四面八方反射出去,我们需要的是其中某一个具体的方向的反射光所携带的能量。
也可以理解为:光携带能量入射到某一个点,这个点会吸收光的能量,然后再从这个点将这部分能量反射释放出去。但是我们不知道往具体某一个方向发射的能量是多少,这时就需要这样一个函数,也就是BRDF。
BRDF描述了光线如何与物体作用,正是这一概念,决定了物体的材质,BRDF项定义了不同的材质。
3.5.1 反射方程:所有入射光对一条反射光线的贡献
3.5.2 渲染方程The Rendering Equation:反射方程+自身发光项
⭐3.5.3 全局光照:对反射方程的理解—直接光照+间接关照
反射出的光=自身发光+Sum((点光源发光)× BRDF(材质) × 入射光角度的cos )
若是面光源,则可由面上的点光源积分而得:
反射方程的一种线性表示形式,其目的在于理解光线追踪下,光线是由直接光照和间接光照组合而成,其中间接光照包括一次直接光照和若干次反弹(这里有些模糊,还是得再回去听一下老师的讲解) :
4.蒙特卡洛路径追踪
4.1 蒙特卡洛积分:求一个复杂函数的定积分—解析解-->数值解
想求一个积分,但是函数形式特别复杂,无法提供一个数学表达式,也就是解析的形式,来计算定积分。
如何解决?通过随机采样值得平均来近似定积分。
蒙特卡洛积分公式:
4.2 路径追踪
思考:Whitted Style的光线追踪一定对吗?
不断去弹射光线,在任何位置都连一条光线。
打到比如玻璃的物体,会发生反射或折射;
打到漫反射的物体,就停下来了。
这两件事真的对吗?
不一定。如下图,镜面反射Whitted可能是对的,但Glossy是错的,他不应该与specular一样的反射
下面一个例子更说明一个问题:光线打到diffuse的物体绝不应该停下来
Whitted是错的,但渲染方程是对的:
渲染方程要解决两个问题:
- 如何对其积分?(在半球面)
- 如何处理递归的过程?(因为弹射的每一个点都来自上一个点所接受的光)
4.2.1 蒙特卡洛法求定积分(简单情形:直接光照)
先考虑一个简单情况,此点不发光,求直接光照的积分结果,也就是说从这一点出发开始追踪,看有多少光线直接达到了光源上:
在这种简单的情况下,我们不考虑此点的自发光,并且也知道半球的PDF,那么就可对其用蒙特卡洛积分来近似结果:
其伪代码如下,很好理解,从这个点向外发出wi根光,如果有一条光线达到了光源,那么就将结果累加这部分能量积分的值。
4.2.2 蒙特卡洛求定积分(全局光照)
那么如何考虑全局光照呢?
假设追踪出去的光线达到了一个物体,而不是光源,同时这个被击中的物体也是受光源影响的,那么此时我们考虑转化问题:
将全局的光照转化为物体之间的直接光照,也就是把物体当做一个光源来看待,就成为了一个局部的直接光照,递归的去求下一个物体的直接光照。
递归的深度,也就是光从光源弹射到像素的次数。
由此,将全局光照的总弹射次数转化为局部的物体之间的“直接光照”
伪代码如下:
但仍存在两个问题:
- 如果一个点弹射一次,发出100根光,在下一次弹射又发出100根光,仅仅两次弹射,仅仅一个点发出的光线,就会有10000根光线发出。这种指数级别的算法是不能接受的。
- 递归何时停止?上文说到递归一定次数停止,但自然界中光线是可以弹射无数次的,如何解决这个问题?
此时先引入路径追踪的基本情况:当N=1时,也就是每个弹射点只发出一根光线的情形,就是路线追踪。伪代码中去掉for循环即可:
此时每个像素点计算radiance的伪代码如下:
那么N=1的情况就是路径追踪,解决了光线数量指数爆炸的问题,那么如何解决递归深度的问题?
俄罗斯轮盘赌!
也就是说,我们以一定概率停止继续往下进行路径追踪。
其原理也比较简单:最后概率的期望仍为定积分的结果:
原理上是对的,但仍然存在一些问题:能不能达到光源完全看运气!
由于是基于概率的事件,点发出的光线数量和光源的大小与概率有很大关系!
很多光线都浪费掉了!
此时需要考虑其他的采样方法。
我们考虑,不在从四面八方进行采样,只考虑在光源的区域进行采样。
但这里有个问题,我在光源区域上采样,却在点的半球区域立体角进行积分,
那么得把渲染方程写成在光源上的积分。如下,需要一个对应关系:单位立体角和单位面积
最后考虑最后一种情况:直接光照是否有物体遮挡