【问题标题】:Question about performance for raytracing algorithm intersection test关于光线追踪算法相交测试的性能问题
【发布时间】:2019-01-22 01:00:41
【问题描述】:

我目前正在构建一个基本的光线追踪算法,并且需要确定哪种处理交叉点的系统在性能方面是最佳的。

在方法中,我正在检查光线和对象的交点,我返回一个结构,其中包含光线行进到命中的距离、命中的位置向量和法线向量或 -1没有交叉点的距离。

对于下一步,我必须找到所有交叉点的最短距离并排除具有负距离的交叉点。

我什至考虑过使用 2 个结构,一个只有负距离,一个完整的结构来减少所需的空间量,但认为这并没有什么不同。

到目前为止我的选择: 首先遍历交叉点的数组并排除具有负距离的交叉点,然后通过排序算法找到与剩余交叉点的最短距离(由于快速实现,可能是插入排序)。

或者将它们放在一个算法中,并在每个排序步骤中测试距离是否为负。

typedef Point3f float[3];
typedef struct {
    float distance;
    Point3f point;
    Point3f normal;
} Intersection;

Intersection intersectObject (Ray-params, object) {
    Intersection intersection;
    //...
    if (hit) {
        intersection.distance = distance;
        intersection.point = point;
        intersection.normal = normal;
    } else {
        intersection.distance = -1.0f;
    }
    return intersection;
}

//loop over screen pixel
    Intersection* intersections;
    int amountIntersections;
    //loop over all objects
    //here I would handle the intersections
    if (amountIntersections) {
        //cast additional rays
    }

我真的不知道处理这个问题的最佳方法是什么,因为这会被调用很多次。交叉点数组可能是一个动态数组,其长度变量为amountIntersections,或者是一个具有最预期交叉点数量的数组,然后其中包含负距离的交叉点。

【问题讨论】:

标签: c performance opengl raytracing


【解决方案1】:

这是我成功用于大量对象的方法。 (特别是对于球棒原子模型;请参阅我的 Wikipedia user page 了解我用于这些模型的方程式。)

首先,将对象转换到眼睛位于原点的坐标系,投影平面平行于 xy 平面,中心位于正 z 轴上。正如您从上面的链接页面中看到的那样,这大大简化了所需的方程式。

举个例子,如果你有一个单位射线n(所以n·n = 1) 和一个以 c 为中心的半径为 r 的球体,射线与球体相交当且仅当 h ≥ 0,

h = (n·c)2 + r2 - (c·c)

如果是这样,在距离 d,

d = n·c ± sqrt(h)

如果您编写出必要的代码并使用合理的临时变量,您会发现可以使用 8 个乘法和 6 个加减法来拒绝不相交的球体,并且可以使用 SSE2/AVX 内在函数轻松地跨对象矢量化(#include <x86intrin.h>)。 (也就是说,不要尝试将 XMM/YMM 向量寄存器用于 nc,而是将每个寄存器组件用于不同的对象,一次计算 2/4/8 个对象的 h。)

对于每条射线,根据已知的最小z坐标对要测试的对象进行排序/选择(例如,cz - r 用于球体)。这样,当您在距离 d 处找到一个交点时,您可以忽略所有最小 z 坐标大于 d 的对象,因为该交点必然会更远,在后面已知的路口。

同样,你应该忽略所有距离小于投影平面距离的交点(即zd / nz,如果平面在 z = zd,并且每条射线只需要计算一次),因为这些交叉点位于眼睛和投影平面之间。 (从技术上讲,如果您将投影平面视为相机,那么您已经“撞到”了某些东西。)

【讨论】:

  • 我应该提供更多信息:我认为我不能真正使用您建议的简化,因为场景将是一个包含一些项目的立方体,并且程序应该能够更改从立方体的每一侧查看,立方体的壁是投影平面(查看方向到立方体的中心)。
  • @Estefunny:当然可以。它只是在开始光线投射之前旋转和平移到对象坐标。起源概念不节省工作的唯一情况是跟踪反射光线。你没有问的是在你开始投射光线之前要做什么。答案是,您对上述坐标系进行旋转和平移,同时对对象进行排序(因此对于每条射线,您只考虑相关/可能的对象,而不是所有对象),丢弃看不见的对象等等。之后,我上面描述的内容如下。
猜你喜欢
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多