【问题标题】:Data structure / approach for efficient raytracing高效光线追踪的数据结构/方法
【发布时间】:2012-12-05 03:31:57
【问题描述】:

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

情况是:

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

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

这当然是在整个应用程序的内部循环中,也是主要的性能瓶颈。它每秒会被调用数百万次,所以我希望尽量减少复杂性/避免不必要的内存分配。

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

或者有没有更聪明的方法来做到这一点?

【问题讨论】:

  • 我不确定这是否会比内存分配更快,但您可以尝试提出一种有效的变换反转算法,然后在退出时将当前光线与逆变换相乘当前对象。
  • @Ivan - 有趣的想法。我想它可能会稍微快一点,虽然我会担心复合数值精度问题.....
  • 您可以预先计算和缓存每个对象(以及组中的对象)的变换和逆变换(即矩阵对象),这些对象将与全局框架相互转换。这样您就不需要嵌套层次结构,因为您可以直接对每个对象进行命中测试。 IE。将光线变换到物体的框架,然后变换回来得到全局框架中的命中点。我在我的跟踪器中这样做:github.com/danieljfarrell/pvtrace

标签: performance algorithm data-structures 3d raytracing


【解决方案1】:

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

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

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

【讨论】:

  • 这是用于视频的方法吗?在场景将被多次渲染的情况下,不是计算每个对象的每条光线的变换不能扩展到世界空间中的对象数量吗?我天真的假设是在交叉点检查时处理转换参数更有效。
  • 相交检查比场景中的对象多得多。所以是的,所有的缓存都会消耗内存以节省 CPU 时间。如果您愿意等待更长时间,您可以决定避免缓存。不过还有更多优化选项。您可以将场景分成(树)组并使用简单的检查边界框。这节省了相当多的 cpu,因为理想情况下只需要对 log n 个对象进行命中测试。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2016-01-08
    • 2017-03-26
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多