7

我正在编写一个 3D 光线跟踪器作为个人学习项目 ( Enlight ),并且遇到了一个与在光线和对象场景之间进行交叉测试相关的有趣问题。

情况是:

  • 我有许多可以与光线相交的基元(球体、盒子、平面等)及其组。我统称为这些场景对象。
  • 我希望能够通过将对象图元包装在一个Transform对象中来对具有任意仿射变换的对象图元进行场景化(重要的是,这将使同一图元的多个实例能够在场景中的不同位置使用,因为图元是不可变的)
  • 场景对象可以存储在包围体层次结构中(即我正在做空间分区)
  • 我的相交测试适用于Ray表示部分射线段的对象(起始向量、归一化方向向量、起始距离、结束距离)

问题是,当光线射中 Transform 对象的边界框时,看起来与包含在其中的已转换图元进行交集测试的唯一方法是将 转换Ray为已转换的坐标空间。这很容易,但是如果光线没有击中任何变换的对象,我需要回退到原始对象Ray以继续跟踪。由于 Transforms 可能是嵌套的,这意味着我必须为Ray完成的每个交集跟踪维护一整堆 s。

这当然是在整个应用程序的内部循环中,也是主要的性能瓶颈。它将每秒调用数百万次,因此我热衷于最大限度地降低复杂性/避免不必要的内存分配。

有没有一种聪明的方法可以避免分配新Ray的/保留Ray堆栈?

还是有更聪明的方法可以做到这一点?

4

2 回答 2

2

大多数时候,在光线追踪中,您有几个(十、千)个物体和更多的光线。可能有数百万条光线。在这种情况下,看看您可以在对象上花费什么样的计算以使其更快/更容易让光线与它们交互是有意义的。

正如boyfarrell 建议的那样,缓存将非常有用。不仅对将它们移入或移出全局框架的对象创建正向和反向变换,而且在全局框架中保留对象的副本,这可能是有意义的。它使创建对象或移动对象变得更加昂贵(因为变换发生变化,缓存的全局帧副本也发生变化),但这可能没关系。

如果你投射 N 条射线并有 M 个对象,并且 N >> M,那么每个对象都会有多条射线击中它是理所当然的。如果我们假设每条射线都撞击一个物体,那么每个物体都有 N/M 条射线撞击它。这意味着将 N/M 射线转换到每个物体,命中测试,并可能将其反转回来。或者每个对象至少 N/M 次变换。但是,如果我们缓存转换后的对象,我们可以对每个对象执行一次转换以到达全局框架,然后不需要任何额外的操作。至少对于命中测试。

于 2012-12-29T23:04:49.520 回答
1

以基本形式定义您的图元(统一比例,以 0,0,0 为中心,不旋转),然后仅使用变换在场景中移动它们。在每个对象中缓存完整的正向和反向转换的结果。(不要忘记法线向量,您将需要它们进行反射)

这将使您能够使用简化的数学来测试命中(您将光线反向转换到对象空间并使用基本形式对象计算命中),然后使用另一个将命中点和可能的反射向量转换回现实世界空间转换。

您将需要计算与场景中所有对象的交点,并选择最接近光线原点(但不是负距离)的命中。为了进一步加快速度,将多个对象封闭在“边界框”中,这将非常简单地计算命中,并且如果命中则将真实世界的光线传递给封闭的对象(但所有对象仍将使用其预先计算的矩阵)。

于 2013-01-21T09:53:07.533 回答