RayTracing光线追踪

Jan 3, 2025

18 mins read

ShadowMapping(阴影贴图)

  1. 从光源视角生成深度图,存储深度值。
  2. 主摄像机渲染场景并计算阴影,与存储的深度值进行比较,如果当前点深度大于阴影贴图深度,说明该点被遮挡是阴影点;否则是光照射的点。

01

缺点:

  • 生成的是硬阴影(点光源)
  • 效果取决于shadowmap分辨率
  • 浮点精度比较问题

由于点光源有大小,会形成如图所示的(Umbra)本影区域和半影(Penumbra)区域。所以会形成阴影的过渡。

02

Question:为什么需要光线追踪?

Answer:光栅化难以做软阴影、难以表现光线多次弹射、光栅化(实时 游戏 快),光线追踪(离线 动画 慢)


光栅化:实时渲染,速度快,但是质量低。

光线追踪:离线渲染,速度慢,但是质量高。

比如疯狂动物城里的一张画面,每一帧渲染需要 10KCPU 核心小时,相当于如果只有100个CPU核,将会花费100个小时才可以渲染完成。

Whitted-Style光线追踪

关于光线3个假设:

1. 假设光线是直线的。
2. 当光线相交时,不会发生碰撞。
3. 光线从光源传播到眼睛,路径是可逆的。(互异性Reciprocity)

其中第3点意味着,当光从光源发出进行弹射后,最终进入眼睛;其实也可以认为是眼睛发射了一束感知光线进行弹射,最终回到光源。

从观察者(相机)出发,射出光线到场景中的物体表面,如果和某个物体相交,说明眼睛能看到这里。再让焦点与光线连接,判断是否有遮挡,如果没有遮挡就形成了一条有效的光路,否则为阴影。

然后对该点进行局部光照模型计算,得到该像素的颜色。

03

假设人眼是一个点,且光线打到物体后会进行完美的反射 / 折射。

  • primary ray:人眼到第一个点的光线路径
  • secondary ray:除了primary ray的其他光线
  • shadow ray:光线与物体交点到光源的光线

每一个交点的颜色贡献来源于直接光照、反射方向间接光、折射方向间接光。

04

求光线与物体的交点

光线的定义如下:

05

求光与球的交点,将光线公式代入到球公式中,解t。可以判断和球是否有交点,有几个交点。

如果是其他隐式几何也是同样联合光线方程。

06

真正在图形学中运用的其实是显式曲面,很多个三角形,因此判断的是光线与三角面的交点。与三角面的焦点可以想象成三角形在一个平面上,就变成了光线与平面的交点了。

光线与平面的交点假设是p‘,那么交点与平面上任何一点p的连线,将会与N(平面的法线)垂直。

之后再判断交点是否在三角形的内部。

08

但是这样一个个计算太麻烦了,于是有了更方便地方法——Möller–Trumbore算法

Möller–Trumbore

利用向量的外积和重心坐标来计算是否相交,大大的提高了效率。

07


在光线追踪中,光线与场景的相交检测是最核心的计算之一。简单的光线相交检测对于每一道光线需要逐一检查是否与每一个物体相交,会遍历每一个三角形进行相交测试,找出离光线最近的交点(最小t值)。但是当场景变得复杂时,三角形数量会变多,使得计算开销增加。

所以会使用一些加速结构(包围盒树、八叉树等)来减少三角形数量,使得光线与场景的相交测试只需要在较小的区域内执行,而非全部三角形。

Bounding Volumes包围盒结构

如果一个光线连包围盒都碰不到,也绝对不会碰到包围盒里的物体。

09

轴对称包围盒:将长方体用3对不同的平面包围住,任何一对平面都与x轴y轴z轴垂直,所以称为AABB包围盒。

10

下图为光线穿过包围盒的3个对面所经历的时间,取这3个时间的交集,就是光线在包围盒里的时间段。

  • 进入包围盒:进入所有对面

    $$ 最晚进入盒子的时间:t_{enter} = max\{t_{min}\} $$
  • 离开包围盒:离开任一对面

    $$ 最早离开盒子的时间:t_{exit} = min\{t_{max}\} $$

11

然而光线并不是直线,光线是一条射线,所以要判断t是否为正数。

当离开的时间<0时,说明盒子在光线的背后;当离开的时间>=0,进入的时间<0,代表光线起点在盒子里面。

12

为什么轴对称包围盒可以提高效率,因为计算公式变得简洁了很多。

$$ t = \frac{(p' - o)·N}{d·N} \qquad t = \frac{p'-o_x}{d_x} $$

光线和盒子有交点并不意味着光线和盒子里的物体相交

如何用AABB加速光线追踪

  1. 把场景包围盒分成多个格子,判断哪些格子可能会有物体。

    15

  2. 光线遇到格子后,如果格子中有物体,就会做一个光线和物体的求交。

    16

如何划分格子?

格子不能太稀疏(1个格子几个物体)也不能太密集(效率低)。格子的数量 = 27(经验所得) 物体的数量*。

毕竟光线会经过所有相交的格子,有些格子也并没有物体。所以在既有大规模的集中,又有大规模的空白,均匀划分格子的方法并不适合。该怎么去划分格子,以至效率高,所以引出了——空间划分的概念。

Spatial Partitions空间划分

在物体稀疏的地方是并不需要很多格子的,在物体密集的时候可以多用一些更小的格子。

空间数据结构 | GeeTeng

近些年KD-Tree很少被使用了,原因是

  1. 很难去求得三角形和包围盒有交集
  2. 如果一个物体同时存在好几个包围盒中,那么一个物体会在多个叶子结点中

13

对于一个场景,场景都是三角形构成的,那通过空间划分的方式会产生一个问题,就是如果给定一个三维空间中的包围盒,我要知道它和哪些三角形有交集,虽然有这个算法,但很难判定一个三角形是否与包围盒(或者立方体)有交集。

虽然三角形只要有一个顶点在盒子里,它俩就算相交了,但有时会出现,三角形的三个顶点都不在盒子里,但它们却是相交的(盒子在三角形内时)

Object Partitions物体划分

BVH的加速结构在图形学中得到了非常广泛的应用,不管是实时的光线追踪,还是离线的结构。

BVH将物体划分成n个部分,划分到一个节点中只有5个三角形为止。

14

BVH避免了求包围盒和物体的交集(因为就是按物体来划分的),也不可能一个物体包含在多个包围盒中,解决了KD-Tree的问题。

但是BVH并没有将空间的严格的划分开,不同的Bounding box可以相交的。所以在实际中要尽可能避免它们之间重叠。

如下是BVH的伪代码,分为三种情况:

  1. 当光线与包围盒没有交点则return
  2. 当交点是叶结点时,和包围盒里的所有物体求交点,返回最近的交点
  3. 如果不是叶结点,就递归地求子部分,最后返回离的最近的交点

18

辐射度量学

辐射度量学是一个精准的给我们一系列物理量的方法,将光精准的定义出来。

Radiant Energy定义:电磁辐射的能量

$$ Q[J = Joule] $$

Radiant flux(power) 辐射通量的定义:单位时间的能量,单位是瓦特 / 流明(lumen)

$$ \Phi\equiv\frac{dQ}{dt} [W = Watt] [lm = lumen] $$

flux的另外一个定义:光线在传播中辐射的各种各样的光子,假如有一个感光平面,单位时间内通过光子的数量就是它的flux。

19

立体角

立体角时一个给定物体从某一特定点所覆盖的视场大小的度量。也就是说测量观察者在看物体时物体有多大的方法。

其中A是球面上一块截取的面积,r是半径。立体角是球面的面积与半径平方的比值。

$$ Ω= \frac{A}{r^2} $$

20

辐照度Irradiance

单位面积接收到的辐射通量:

$$ E(X) \equiv \frac{d\Phi(X)}{dA} $$

假设一个点光源以总功率 Φ进行均匀的球面辐射。内球半径为1,外球半径为r。

内球的辐照度是flux / 4pi,其中4pi是球面的表面积

intensity并没有改变,是irradiance变小了,原因是在传播过程中照射到的面积变大了。

21

辐亮度Radiance

辐亮度是单位立体角和单位投影面积上,由表面反射、发射或接受的能量,在特定方向上的能量。

22

如果想计算总入射辐照度,需要对所有方向的辐射亮度积分。

辐射亮度L(p,w)代表某个方向上的光线强度,如下公式表示Irradiance是Radiance在所有方向上的积分。

辐亮度强调方向性,某个方向的亮度,不随距离变化。而辐照度描述的是某个表面收到的光。

23

BRDF

一个点在接收一束光照射之后,会将这束光反射到空间半球中的任何一个可能的方向(取决于物体的材质),BRDF描述的就是向某一个方向反射出去的光的量与这束入射光总的量的比值(从入射方向入射到表面后,在出射方向的反射比率)

24

Rendering Equation渲染方程

渲染方程由表面自身的辐射和环境的入射光构成。

H平方或者Ω都代表半球。

25

如下图公式中包含了:由其他物体反射或发出的光线、多个点光源、存在面光源。

26

通过一系列将方程简化,得到下列式子,光线弹射一次叫直接光照、光线弹射两次叫间接光照、光线弹射超过两次就叫做全局光照

27

Sharing is caring!