PBRT 第十七章笔记 | Notes for PBRT Chapter 17 - Retrospective and The Future

17.1 Design Retrospective

PBRT 在设计上的一个基础的假设在于:支持复杂和多样的场景、形状、材质、光源和采样算法具有非常高的重要性,且为了得到这样的效果,付出计算开销是值得的。这种假设的一个后果在于 PBRT 在简单场景的渲染效率上表现不佳。

一个例子是,在 PBRT 里确定表面的 BSDF 的过程比那些不需要对材质滤波或是计算光线微分的渲染流程而言更为费时。我们假设了这一做法可以在复杂场景和材质下有效地减少对相机光线的需求量,但对于简单场景而言抗锯齿通常并不是很严重的问题。另一方面,PBRT 中的很多采样算法假设了每个像素都要至少采样成百上千次以得到高品质的全局光照,在这种情况下,因为本来就已经采样了很多相机光线,对材质进行抗锯齿的操作带来的提升也有限。

另一方面,系统中的一些简化的接口也造成了不必要的重复工作。例如 Sampler 无论是否需要都会提供镜片位置和光线时间给相机,而相机无法告知采样器以避免这些开销。同样的,Integrator 也常常会抛弃没有被使用的采样序列。这主要是为了让读者能够更好地了解整个系统而设计的。

书中的练习中包括了一些重要的设计替代,即使你不打算实际上手实现它们,也应该至少读一读。

扎心了,大部分我都没看

17.1.1 Triangles Only

对不同几何体的支持给 PBRT 带来了不小的性能开销,它虽然看上去十分优雅,但在大部分实践的情况下都是不必要的。大部分实际使用的模型都是由三角形建模,或者用复杂的,难以实现光线相交算法的样条线等数学工具生成的,后者在渲染时常常会被转化为三角形表示。

只使用一种底层形状表示方法的好处有很多,包括了:

  • 渲染器可以依赖于三角形顶点可以直接转换到世界坐标下,而无需进行到物体坐标系的转换
  • 加速结构可以更加的专一化,让其中的节点直接储存对应的三角形而非整个几何体,这可以提高内存局部性,并避免多层虚函数的调用
  • displacement mapping 在这种情况下更容易实现

这些优势可以带来巨大的性能提升和复杂度降低,在生产用渲染器中是非常值得考虑的一点。

17.1.2 Increased Scene Complexity

给定一个构建好的加速结构,光线追踪的一个好处在于光线 - 物体相交的复杂度随场景复杂度的增长较为缓慢,这使得内存表现相对计算能力而言更容易影响渲染器的效率。由于光线会经过大量不同的区域,它并不是一个对虚拟内存或缓存的结构。

一种解决方案是减少内存的占用量,这需要对系统中的内存使用非常的小心。减少内存占用的方式包括了更紧凑的三角形表示、几何体和颜色压缩等等。

另一种更复杂的方法则是几何体缓存和光线优化。通过对几何体进行缓存并优化采样的顺序,也可以有效地提升效率。

17.1.3 Production Rendering

渲染用于电影的高品质图像也引入了一系列挑战,如极其复杂的场景和材质。大部分生产用的渲染器都具有对几何体和材质的延迟加载和缓存机制。可编程的表面着色器对于复杂材质的实现同样十分必要。

另一个时间上的挑战在于结合交互性的建模和着色工具。让艺术家可以快速地看到他们对场景的修改非常重要,这需要工具之间的的深度结合。

17.1.4 Specialized Compilation

2010 年提出的 OptiX 光线追踪渲染系统具有非常有趣的设计,它在内置的功能基础上可以被用户提供的代码进行拓展。很多近年的渲染器都允许经过插件等方法提供一定的用户拓展性,但 OptiX 特别在于它可以构建于一个运行时编译系统之上。由于编译器拥有对于整个系统的信息,产生的自定义渲染器可以快速且自动地专一应用于一系列内容中。

17.2 Alternative Hardware Architectures

本书主要以传统的多核 CPU 作为系统的目标架构,且并没有使用其中的 SIMD 功能。虽然其它更专一化的设备如 GPU 可以带来更多的性能提升,这些设备的特性会经常改变,且其编程语言和模型也较为小众。PBRT 3ed 并没有利用这些特性,但它们值得讨论。

早期的光线追踪主要关注于多处理器和渲染集群的工作,而最近计算性能的提升让关注的重点改变到 CPU 的 SIMD 和 GPU 上。

CPU 一种被设计为一个注重串行性能的处理器,随着可编程图像处理器的出现,流处理器在现代计算系统中正在变得越来越重要。这类处理器并不特别关注单线程的效率,而是注重多个并行线程的表现。这种特性让流处理器对缓存、分支预测的需求变低,从而可以在同样的芯片面积上提供更多的 ALU 用于计算。

SIMD 是流处理器的关键机制,现代 CPU 和 GPU 都有在其核心内拥有 SIMD 向量单元,而其中的核心和并行数量也正在随着时间迅速增长。

17.2.1 GPU Ray Tracing

在 GPU 上实现光线追踪面临着一系列挑战,包括加速结构的构建、计算的分散性和有限的局部内存。GPU 对数据局部性的要求很高,而加速结构常常通过一系列链接在内存中四处分散查找;且每条光线之间的计算内容也天差地别,并需要不小的内存以储存中间信息。

一种有趣的实现方法是使用一个光栅化渲染器和平行投影以跟踪光线,从而得到在一个方向上的可视化测试结果。虽然这种方法并不能提供有效的采样信息,但其性能提高可以在一定程度上弥补这一损失,但这一方法长远来看似乎不那么有可拓展性。

17.2.2 Packet Tracing

对于并行数据更少的情况,如 CPU 上的 SIMD ,可以通过机会主义地使用 SIMD 设备以提升一定的性能。如对 Spectrum 类型使用 SIMD 并行计算各个通道。这些优化有时可以通过编译器完成。

想要充分利用 SIMD 的向量单元需要整个计算过程被表示为并行的数据形式,相同的操作被应用于一系列数据上。光线追踪渲染器实现中的一种基础的实现数据并行的方法是称为 Packet Tracing ,它让设备同时跟踪 nn 条光线。虽然 SIMD 使用率会很高,但这无法解决不同的光线需要不同的数据和计算的问题。

这种解决方案可以成功地实现高性能的 CPU 光线追踪渲染器,摄像机会同时生成一组 nn 条光线,接着作为整体一起处理。加速结构被修改为如果任意光线与其相交都会测试其子几何体。这一方法被证明可以提供不小的性能提升,但其效果严重受限于光线之间的相关性。

Packet Tracing 在 CPU 上通常被显式地实现。相交函数会接受光线数量作为输入。与之相对的,对于流处理器的向量化操作通常是隐式的。代表通常被写做和接受单一数据输入,并被底层的编译器和硬件并行执行。

Reshetov 等人在 2005 年发表的论文中拓展了 Packet Tracing 方法,其中使用了锥体完成加速结构的遍历以提供高效的光线追踪。而后被 Reshetov 和 Benthin 与 Wald 等人进一步发展到剔除和阴影光线上。

虽然 Packet Tracing 对于一致性较好,即相交顺序相近的光线组合而言可以提供不错的效率,但对于全局光照中更常见的非一致性光线而言则不那么有效。一种解决方案是将 SIMD 应用于加速多个包围盒的相交计算中。另一种方法则是重新规划光线组以将具有一定相似性的光线放入一组后再进行计算。

Embree System 是一个同时支持高效单射线遍历和 Packet Tracing 的开源渲染系统,于 2014 年被 Wald 等人在论文中提出。

事实上,当一个渲染器可以同时提供大量需要相交测试的光线时,还可以使用很多其它高效的算法。Keller, Wächter 和 Mora 在 2011 年提出了一种可以对大量光线和无加速结构的场景进行高效相交的算法。这种算法同时对光线和几何体进行空间划分,直到子空间内只存在一小部分光线和几何体为止再执行相交测试。

17.2.3 Ray-Tracing Hardware

基于已经十分成功应用于光栅化的图形处理器,长久以来对光线追踪专用的计算硬件的关注一直不减。光线追踪本身具有大量的可定制的阶段可以被专用硬件加速。

早期的工作包括 Woop 等人 2005 年提出的 ray processing unit (RPU) 设计,更近一点地,Aila 和 Karras 于 2010 年提出了一种通用的架构以解决全局光照算法中不一致的光线。而后 Nah 、Lee 和 Doyle 等人还发表了一系列有关光线追踪的论文,其中描述了大量有关移动设备的光线追踪、结构遍历、光线生成、相交计算、光线排序、加速结构生成等等问题。

17.2.4 The Future

近年来,有关高性能图形架构的创新可能会越来越多。随着 CPU 逐渐增加其 SIMD 的宽度并加入更多处理核心,它们会变得越来越像流处理器,而流处理器则可能加入更多对任务并行和非一致性任务的支持。未来计算机系统会是由多种专一处理器构成还是说由一个通用处理器构成这一点仍然是一个开放的问题。

另一方面,专用图形硬件可能在未来变得更加重要,它们相比可编程的核心而言更加的高效、节能。随着计算流程的逐渐固化,固定功能的专用硬件可能会更加普遍。

17.3 Conclusion

这章作为结语就不记笔记了