Ray Tracing
Three ideas about light rays:
-
光线沿直线传播
-
光线相交时互不影响,不会存在碰撞
-
光路可逆
基于光路可逆的这个原则,我们在做ray tracing的时候实际上是从眼睛(摄像机)处发射一道光线,经过弹射后进入光源,完成一条光路,再通过shading模型计算当前的image plane上的着色。
Whitted-Style Ray Tracing
使用的是一个递归的方法,完成对场景中多次弹射的光线的追踪,当光线打到光滑物体表面时,进行反射和折射;当光线打到漫反射表面时,光线停止弹射。
如上图,由eye point发出的一条光线,经过了不同程度的折射和反射之后到达光源,我们将能够到达光源的三个点(有一个点被三角形遮住了而无法被照亮)处的着色相加,即为image plane在这个像素中所能看到的最终结果。
最关键的点在于如何计算光线与物体相交?
在这个矢量场里,我们将光线传播的公式记为:r(t) = o+td,其中t是传播的时间,o是光源的位置,d是光传播的方向。
接下来只需要我们做出空间内物体的表达式,将两个表达式联立起来求交集即可。
Bounding Volumes
包围盒理论,能加速计算光线是否相交——如果光线没有与包围盒相交,那就必然不会与包围盒内的物体相交。
Axis-Aligen Bounding Boxes(AABBs)
加速的方法
uniform grids
- 找到一个当前场景的包围盒。
- 将包围盒划分为均匀的格子(grid)。
- 找到与物体表面相交的格子。
- 在光线传播的路径中寻找其是否与上面的格子相交。
因为计算光线与格子相交要比计算光线与物体相交要容易,所以这个做法可以加速计算。
当格子的数量划分的太多时,计算光线与格子相交的计算量会变大。当格子的数量划分的太少时,又不太能起的到加速的效果。工业界由经验得来的一般性的结论是:在三维场景中,划分的格子数量是包围盒内物体数量的27倍。
uniform grids在物体密集的场景中效果较好,但是在一些空旷的场景中(Teapot in a stadium)则会耗费大量的不必要资源。
Spatial Partitioning
-
八叉树:一维二叉,二维四叉,三维八叉。
-
KD -Tree:主要是为了解决八叉树在高维过于庞大的问题,在每一次切割时,只切割一刀,因此,不论维度,可以直接用一个二叉树。表示。
-
BSP-Tree:也是只切一刀,但是不一定要水平切,可以斜着切。
KD-Tree
KD数的存储结构:
-
中间节点存储:
-
分割的方向:x轴,y轴,z轴
-
分割的坐标位置
-
子节点
注意,中间节点不存储物体
-
-
叶子节点存储:该区域内的物体
KD树的遍历:不断取相交即可。
Bounding Volume Hierarchy(BVH)
层次包围盒,划分的不是空间,而是直接划分物体,将一个包围盒拆成两个小的包围盒。
一些在划分的时候可以使用的技巧:
-
可以总是选择最长的那一个轴进行切分
-
切分时可以选择中点,以此保证树的平衡