Part 6 光线追踪
约 1188 字大约 4 分钟
2025-04-08
至此,我们基本学习完了光栅化成像的内容。不可否认,光栅化成像符合直觉、计算效率高,但是如软阴影、多次光线反射、高质量渲染等场景下,光栅化成像就显得力不从心了。
而光线追踪可以解决这些问题。
在光线追踪中,有几个原则:
- 光沿直线传播;
- 光线与光线之间不会发生碰撞;
- 光线从光源出发,经过若干次反射、折射后进入人眼;
- 光路可逆。
1 光线追踪基本原理
一种常见的光线追踪算法称为光线投射。对于成像平面上的某一像素,从相机处投射一条视线穿过该像素,到达模型上的某一点。然后再从光源向该点处投射一条光线,若光线没有被遮挡,则该点可见,形成了一条有效的光路,此时即可着色。
但是该算法只考虑了一次反射。作为该算法的改进,Whitted-Style 光线追踪会递归计算人眼投射出的视线的反射和折射,并将每次反射和折射的结果叠加计算作为像素的值。
容易看出,在光线追踪的计算中,关键在于折射和反射,也就是求解光线和模型的交点。
我们定义光线是一条射线,因此其具有起点和方向:
r(t)=o+td
其中t≥0。
曲面是若干点p的集合,满足:
f(p)=0
交点即同时满足光线方程和曲面方程,将光线代入球面方程得到:
f(o+td)=0
解得t的值,代入光线方程r(t)=o+td即可得到交点坐标。
以上是一个数学曲面(平面也算曲面)。然而我们的模型都是三角形组成的,该如何求解光线与三角形的交点?
我们知道三点一定共面,因此我们只需要求解光线与平面的交点,然后判断该交点是否在三角形内即可。
提示
采用向量叉乘来判断点是否在三角形内。
当然,还有一种直接给出交点重心坐标的 Möller Trumbore 算法:
我们把三角形p0p1p2用重心坐标表示:
o+td=(1−b1−b2)p0+b1p1+b2p2
有:
tb1b2=S⋅E11S2⋅E2S1⋅SS2⋅D
其中:
E1E2SS1S2=p1−p0=p2−p0=o−p0=d×E2=S×E1
当t,b1,b2同时满足下列条件时,结果具有物理意义:
t≥00≤b1≤10≤b2≤10≤b1+b2≤1
2 光线与曲面求交加速
2.1 轴对齐包围盒
在三角形的光栅化中,我们不可能逐个判断所有像素是否在三角形内。而是计算三角形的包围盒,对包围盒内的像素进行判断。
同样,我们在计算光线和模型求交时,也不可能计算所有三角形,而是去计算包围盒内的三角形。
对于一个复杂形状的模型,我们用一个相对简单的包围盒包围。如果连包围盒都没有与光线的交点,那么模型一定也没有交点。
最常用的包围盒称为轴对齐包围盒(Axis-Aligned Bounding Box, AABB)。AABB 的每条边都与坐标轴平行,这可以显著减少计算量。
我们以一个二维 AABB 为例说明如何计算,三维同理。
二维 AABB 可以由x0,y0,x1,y1来表示。
我们先计算光线与两条纵向边界x0和x1的交点,得到对应的一组txmin和txmax。
然后计算光线与两条横向边界y0和y1的交点,得到另一组tymin和tymax。
比较txmin和tymin,取其较大者作为tmin;比较txmax和tymax,取其较小者作为tmax。
当tmin<tmax且tmax>0时,说明光线与 AABB 有交点。
三维 AABB 同理。