如何光线追踪不适合记忆的场景?


11

如果要进行光线跟踪的场景无法存储在内存中,那么在不向机器添加更多RAM的情况下,在实际的时间范围内渲染场景似乎是不现实的,因为需要从磁盘上加载场景的不同部分,每个像素可能需要多次加载。

有没有办法解决?我正在尝试一种某种方式来一次执行涉及场景的特定子集的大量计算,以减少需要将其加载到内存中的次数。在这种情况下还有其他提高速度的方法吗?

Answers:


10

如果场景不完全适合内存,则您将进入核心外渲染字段。这里基本上有两种方法:a)按需生成场景b)按需加载场景

前一种方法与大多数动画工作流程非常吻合,其中使用例如Catmull-Clark对模型进行了细分,并且可能占用大量内存,但是基本网格物体本身很容易装入内存。皮克斯(Pixar)对此有几篇论文(例如,用于复杂场景中的分布射线跟踪的射线微分和多分辨率几何缓存),但是要点是,仅当模型被射线照射时才对其进行细分,并且仅对其进行尽可能多的细分。对于这种射线是合理的(例如,漫反射比镜面反射的精度要低)。其余的由几何高速缓存处理,该高速缓存将细分的模型保留在内存中,并希望通过良好的逐出策略提高处理效率。

只要您所有的基础网格都能舒适地适合内存,您就可以轻松地移出核心并以细分级别渲染网格,而这些细分级别永远不会适合内存。几何缓存还可以根据您拥有的内存量很好地扩展,从而可以权衡RAM与渲染时间。我相信这也用在了汽车上

第二种方法更通用,不依赖大量使用细分。取而代之的是,它依赖于这样一个事实,即您的场景很可能是由艺术家制作的,并且已经被划分为可放入内存的合理的小物体。然后,想法是保留两个层次结构(kD树或边界体积层次结构):顶层层次结构仅存储场景中对象的边界框,而底层层次结构存储实际的几何图形。每个对象都有一个这样的低级层次结构。

通过这种方法,理想情况下,您已经在磁盘上与每个对象一起存储了一个边界框。加载场景时,最初只构建顶层层次结构,这意味着您只需要查看边界框,而不是几何体。然后,您开始跟踪射线并遍历层次结构。每当射线击中顶层层次结构中的叶节点(即它击中对象的边界框)时,该对象就会被加载到内存中并构建其低层层次结构。然后,射线继续向下跟踪该对象。与对象缓存结合使用,该缓存将尽可能多的低级层次结构保留在内存中,因此可以很好地执行。

这种方法的第一个好处是,永远不会加载从未命中的对象,这意味着它会自动适应场景中的可见性。第二个好处是,如果要跟踪很多射线,则不必立即加载对象,因为它会被射线击中。取而代之的是,您可以握住该射线并等待,直到有足够的射线击中该对象,从而分摊多次射线击中的负载。

您也可以将此方法与射线排序算法(例如用于生产路径跟踪的“排序的递延阴影”)结合使用,以避免由于不相干的射线造成的抖动。上面提到的纸张描述了迪士尼的Hyperion渲染器的体系结构,我相信它可用于Big Hero 6,因此它很可能可以处理生产规模的场景。


1
超级有趣!您链接的迪士尼论文也是如此。
John Calsbeek

+1对我一直想知道的事情的答案!
2015年

7

如果以空间结构组织场景(通常的方法是“ 边界体积层次结构”),则可以使用一种虚拟场景(我指的是虚拟纹理)。

内存管理器一次只能加载有限数量的边界框,并抽象化检索一个边界框的操作。

这样,仅在需要时才加载框:当射线撞击边界框时,将加载该框以解决碰撞。稍后,当需要装入另一个盒子时,未使用的盒子将被删除以为新盒子腾出空间。

随着所有这些盒子的加载和删除,射线相干性将成为速度的主要因素。我想进一步的改进可以是通过重新排序射线以首先处理已经加载的盒子来推迟加载。


是的,像这样。
joojaa 2015年

1

您要做的是根据先前遇到的情况将三角形从磁盘加载到内存中。您可以先从紧邻的三角形开始。原因是在一个区域中,射线很可能会反复打到相同的三角形。最终您会有所效率。(因此,在无关紧要的遮挡跟踪中缓存最后命中的三角形是个好主意)

其次,您将三角形存储在空间树中,该树使您可以从磁盘进行快速搜索,以按距离更新内存中的哪些部分。因此,仅加载会阻碍光线的分支。如果它是某种体素树(如八叉树),您甚至可以对次要射线进行分类并通过相干来解决它们。BSP树在修剪区域也有些不错。

在某些情况下,此操作会失败,但是如果您不渲染噪音,则在大多数场景存储区中它都相当有效...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.