我正在编写一个3D光线跟踪器作为个人学习项目(Enlight),并遇到了一个与在光线和物体场景之间进行交叉测试相关的有趣问题。
情况是:
Transform
对象中来对具有任意仿射变换的场景对象进行渲染(重要的是,这将使得相同图元的多个实例能够在不同的位置使用场景,因为原语是不可变的)Ray
个对象(起始矢量,标准化方向矢量,起始距离,结束距离)问题在于,当光线撞击Transform对象的边界框时,看起来与包含在其中的变换图元进行交叉测试的唯一方法是将Ray
转换为变换后的Co-纵坐标。这很容易,但是如果光线没有碰到任何变换的物体,我需要回到原来的Ray
继续追踪。由于Transforms可能是嵌套的,这意味着我必须为每个完成的交集跟踪维护一整套Ray
s。
这当然是整个应用程序的内部循环和主要性能瓶颈。它将被称为每秒数百万次,所以我渴望最小化复杂性/避免不必要的内存分配。
是否有一种聪明的方法可以避免分配新的Ray
s /保留Ray
堆栈?
或者是否有更聪明的方式完成这项工作?
答案 0 :(得分:2)
大部分时间在光线追踪中,你有几个(数百,千)个物体和相当多的光线。可能是数百万的光线。在这种情况下,有必要了解您可以在对象上花费哪种计算,以使光线更快/更容易地与光线进行交互。
如boyfarrell建议的那样,缓存将非常有用。不仅可以在将对象移动到全局帧或从全局帧移动的对象上创建正向和反向变换,而且还可以在全局帧中保留对象的副本。它使创建对象或移动它们变得更加昂贵(因为转换发生了变化,缓存的全局帧副本也发生了变化),但这可能没问题。
如果你施放N射线并拥有M个物体且N>> M然后理所当然地说每个物体都会有多条射线击中它。如果我们假设每条射线都撞击一个物体,那么每个物体都会有N / M射线撞击它。这意味着将N / M光线转换为每个对象,进行测试,并可能将其反转。或者N / M至少转换每个对象。但是如果我们缓存转换的对象,我们可以对每个对象执行单个转换以获得全局帧,然后不需要任何额外的转换。至少对于命中测试。
答案 1 :(得分:1)
以基本形式定义基本体(统一比例,以0,0,0为中心,不旋转),然后仅使用变换在场景中移动它们。缓存每个对象中完整的正向和反向转换的结果。 (不要忘记法线向量,你需要它们进行反射)
这将使您能够使用简化的数学测试命中(您将光线反向转换为对象空间并使用基本形式对象计算命中),然后将命中点和可能的反射向量转换回现实世界空间使用其他变换。
您需要计算场景中所有对象的交点,并选择最接近光线原点的击中(但不是负距离)。为了进一步提高速度,请将多个对象包含在"边界框中。这将是非常简单的计算命中,如果命中,将把现实世界的光线传递给封闭的对象(但是所有对象仍将使用它们的预先计算的矩阵)。