24

我正在用 D ( http://dsource.org/projects/stacy ) 编写一个相对简单的光线追踪器/路径追踪器,但即使经过全面优化,每条光线仍需要数千个处理器周期。我还能做些什么来加快速度吗?更一般地说,您知道光线追踪的良好优化/更快的方法吗?

编辑:这是我已经在做的。

  • 代码已经高度并行运行
  • 临时数据以缓存高效的方式结构化,并与 16b 对齐
  • 屏幕分为 32x32 块
  • 目标数组的排列方式使得块中的所有后续像素在内存中都是连续的
  • 执行基本场景图优化
    • 对象的常见组合(如盒子中的平面 CSG)被预先优化的对象替换
  • 能够利用 GDC 的自动矢量化支持的矢量结构
  • 射线上的后续命中是通过惰性求值找到的;这可以防止对 CSG 进行不必要的计算
  • 既不支持也不优先的三角形。仅普通图元,以及 CSG 操作和基本材料属性
  • 支持边界
4

9 回答 9

11

光线追踪器速度的典型一阶改进是某种空间分区方案。仅基于您的项目大纲页面,您似乎还没有这样做。

可能最常用的方法是八叉树,但最好的方法很可能是方法的组合(例如空间分区树和邮箱等)。边界框/球体测试是一种快速廉价且令人讨厌的方法,但您应该注意两点:1)它们在许多情况下没有多大帮助;2)如果您的对象已经是简单的基元,您将不会获得太多收益(甚至可能会输)。您可以更容易(比八叉树)为空间分区实现规则网格,但它仅适用于稍微均匀分布的场景(就表面位置而言)

很大程度上取决于您所代表的对象的复杂性、您的内部设计(即您是否允许本地转换、对象的引用副本、隐式曲面等),以及您想要达到的准确度。如果您正在编写具有隐式表面的全局照明算法,则权衡可能与您正在为网格对象或其他任何东西编写基本光线追踪器时有所不同。我没有详细查看您的设计,所以我不确定您已经考虑过以上哪些内容(如果有的话)。

像任何性能优化过程一样,您必须首先进行测量以找到您实际花费时间的地方,然后改进事物(根据偏好进行算法,然后根据需要进行代码混乱)

于 2009-04-22T16:10:22.270 回答
9

我从光线追踪器中学到的一件事是,许多旧规则不再适用。例如,许多光线追踪算法会进行大量测试以“尽早”完成计算量大的计算。在某些情况下,我发现消除额外的测试并始终运行计算以完成要好得多。算术在现代机器上很快,但错过的分支预测代价高昂。通过用最少的条件分支重写它,我的光线-多边形相交测试的速度提高了 30%。

有时最好的方法是违反直觉的。例如,当我将它们分解为大量较小的对象时,我发现许多包含几个大对象的场景运行得更快。根据场景几何,这可以让您的空间细分算法抛出大量的交叉测试。让我们面对现实吧,相交测试只能这么快进行。您必须消除它们才能获得显着的加速。

分层边界体积有很大帮助,但我最终摸索了 kd-tree,并获得了巨大的速度提升。当然,构建树的成本可能会使实时动画望而却步。

注意同步瓶颈。

您必须进行简介以确保将注意力集中在正确的位置。

于 2009-05-26T23:29:18.647 回答
6

我还能做些什么来加快速度吗?

D,取决于实现和编译器,提出了相当好的性能。由于您还没有解释您已经使用了哪些光线追踪方法和优化,因此我无法为您提供太多帮助。

然后,下一步是对程序运行时序分析,并重新编码最常用的代码或最慢的代码,而不是在汇编中影响最大的性能。

更一般地,请查看以下问题中的资源:

我真的很喜欢使用显卡(大规模并行计算机)来完成一些工作的想法。

本站还有很多其他的光线追踪相关资源,其中一些在本题的侧边栏中列出,大部分都可以在光线追踪标签中找到。

于 2009-04-22T16:12:22.577 回答
3

一些建议。

  • 使用边界对象快速失败。
  • 第一步投影场景(就像普通显卡一样),光线追踪仅用于光照计算。
  • 并行化代码。
于 2009-04-22T16:15:18.657 回答
3

我完全不懂D,所以看代码也找不到具体的优化,但我可以说一般。

这真的取决于你的要求。最简单的优化之一就是减少任何特定光线可以跟随的反射/折射的数量,但是你开始失去“完美的结果”。

光线追踪也是一个“令人尴尬的并行”问题,所以如果你有资源(例如多核处理器),你可以考虑并行计算多个像素。

除此之外,您可能只需要分析并弄清楚究竟是什么花了这么长时间,然后尝试优化它。是路口检测吗?然后努力为此优化代码,依此类推。

于 2009-04-22T16:11:46.900 回答
3

每隔一个像素进行光线追踪。通过插值获得中间的颜色。如果颜色变化很大(您位于对象的边缘),请对中间的像素进行光线追踪。这是作弊,但在简单的场景中,它几乎可以在牺牲一些图像质量的同时将性能提高一倍。

在 GPU 上渲染场景,然后将其加载回来。这将为您提供以 GPU 速度命中的第一条光线/场景。如果场景中没有很多反射表面,这会将您的大部分工作减少为普通的旧渲染。不幸的是,在 GPU 上渲染 CSG 并不完全简单。

阅读 PovRay 的源代码以获得灵感。:)

于 2010-07-22T03:56:18.590 回答
2

您必须首先确保使用非常快的算法(实现它们可能会很痛苦,但是您想做什么以及要走多远以及应该多快,这是一种权衡)。

来自我的更多提示 - 不要使用邮箱技术,在论文中有时会讨论它们由于计数开销而无法与实际架构很好地扩展 - 不要使用 BSP/Octtrees,它们相对较慢。-不要使用 GPU 进行光线追踪,它对于反射和阴影、折射和光子映射等高级效果来说太慢了(我只将它用于着色,但这是我的啤酒)

对于一个完整的静态场景,kd-Trees 是无与伦比的,而对于动态场景,有一些聪明的算法可以在四核上很好地扩展(我不确定上面的性能)。

当然,为了获得真正好的性能,您需要使用非常多的 SSE 代码(当然不会有太多的跳转),但对于不是“那么好”的性能(我在这里谈论的可能是 10-15%)编译器内在的东西就足够了实施你的 SSE 东西。

还有一些关于我正在谈论的一些算法的不错的论文:

《Fast Ray/Axis-Aligned Bounding Box - Overlap Tests using Ray Slopes》(very fast very good paralelisizable (SSE) AABB-Ray hit test)(注意,论文中的代码并不是全部代码,只是google一下标题纸,你会找到的)

http://graphics.tu-bs.de/publications/Eisemann07RS.pdf

“使用动态边界体积层次结构的光线追踪可变形场景”

http://www.sci.utah.edu/~wald/Publications/2007///BVH/download//togbvh.pdf

如果您知道上述算法的工作原理,那么这是一个更强大的算法:

“在动态场景中使用预先计算的三角形集群进行加速光线追踪”

http://garanzha.com/Documents/UPTC-ART-DS-8-600dpi.pdf

我还使用 pluecker-test 来确定快速(不准确,但好吧,你不能拥有所有)如果我击中一个多边形,在 SSE 及更高版本上工作得非常好。

所以我的结论是,那里有很多很棒的论文,涉及很多与光线追踪相关的主题(如何构建快速、高效的树以及如何着色(BRDF 模型)等等),这是一个真正的“实验”这个神奇而有趣的领域,但你也需要有很多空闲时间,因为它非常复杂但很有趣。

于 2010-07-17T22:09:00.013 回答
0

你可以

  • 使用 SAH 优化的包围体层次结构......
  • ...最终使用数据包遍历,
  • 引入重要性抽样,
  • 访问按 Morton 代码排序的切片以获得更好的缓存一致性,以及

更多——但这些是我能立即想到的建议。更多的话:

您可以基于统计数据构建优化的层次结构,以便在与几何体相交时快速识别候选节点。在您的情况下,您必须将自动层次结构与建模层次结构相结合,即约束构建或让它最终克隆建模信息。

“数据包遍历”意味着您使用 SIMD 指令来计算 4 个并行标量,每个标量都有自己的射线用于遍历层次结构(通常是热点),以便从硬件中获得最大的性能。

您可以执行一些每条光线的统计数据,以便根据对生成的像素颜色的贡献来控制采样率(二次光线拍摄的数量)。

在图块上使用面积曲线可以减少像素之间的平均空间距离,从而降低性能从缓存命中中受益的可能性。

于 2012-09-04T16:38:40.857 回答
0

我的第一个问题是-您是要优化单个静止屏幕的跟踪,还是要优化多个屏幕的跟踪以计算动画?

优化单次镜头是一回事,如果您想计算动画中的连续帧,则需要考虑/优化很多新事物。

于 2009-05-21T00:45:47.497 回答