虽然这篇入门文章关注的是硬件架构层面,但在软件层面光线追踪API功能的两个不同层面也存在差异。第一个也是更简单的层次是“内联光线追踪”,也被称为“光线查询”。从根本上说顾名思义这种光线追踪的方法设置了带有关联状态的光线,然后继续进行光线查询:光线通过BVH进行追踪,并将报告其结果。本质上,这正是第2级和第3级解决方案在硬件上所做的--循环通过盒测试和最终光线三角形测试,然后报告所需的结果,这被简化为命中或错过。一个简单的例子是发送一个光线查询到一个光源;如果光线照射到不透明的物体,我们就知道自己处于阴影中,但是如果光线照射到光源,我们就知道像素被照亮了,因此基于这个简单的光线查询,我们现在实现了光线追踪阴影:
Setup Ray (myRay)
AnyHit = RayQuery (myRay)
If (AnyHit = TRUE)
Execute Shadow code
Else
Execute Lit code虽然上面的例子很简单,但并不是大多数人所认识到的光线追踪——也就是说,光线在环境中来回反射,从而产生复杂的光线反射效果。这种更复杂的光线追踪形式被称为"全光线追踪"并且它确实做到了;当光线命中/错过对象时,它会创建新的着色程序并执行。
光线从一个着色程序中发射出来,照射到另一个物体,这个物体又会启动另一个着色程序,而这个着色程序又会启动另一条光线,光线又会启动另一个着色程序,以此类推,这就是所谓的递归。递归的结果是一个着色器程序的堆栈,这个过程会一直持续下去,直到你的光线在某个地方停止反弹,然后你将堆栈倒回,收集在场景周围跟踪光线的所有处理阶段。
从概念上看,它是这样的:
EmitRay (Ray1)
Hit Object which EmitRay (Ray2)
Hit Object which EmitRay (Ray3)
Hit Object – execute shader program
Execute shader program which takes previous hit data into account
Execute shader program taking both the previous two hits data into account
Original program which takes the whole ray data flow into account这种类型的递归是复杂的,因为正如您从上面看到的,阶段堆栈在开始之前有一个未知的深度,因为您不知道射线会或不会击中什么对象。这使得它成为一个非常动态和多阶段的过程,每个阶段都需要存储和资源。这就是所谓的“全光线追踪”,比光线查询功能更强大,但也更复杂。Imagination Technologies作为光线追踪的先驱之一,开发出了一种既支持内联光线追踪(光线查询)又支持全光线追踪的架构。
等级4-基于硬件相关分类的BVH处理