通过Compute Shader对屏幕Quad进行光线跟踪

时间:2017-05-25 13:31:15

标签: opengl graphics fragment-shader raytracing compute-shader

我最近正在通过opengl教程寻找光线追踪。大多数教程都更喜欢计算着色器。我想知道为什么他们只是渲染到纹理,然后将纹理渲染为四边形。

计算着色器方法在屏幕四边形上的优缺点是什么?

1 个答案:

答案 0 :(得分:7)

简短回答:因为计算着色器为您提供了更有效的工具来执行复杂的计算

答案很长:

或许他们提供的最大优势(在跟踪的情况下)是能够准确控制如何在GPU上执行工作。当您跟踪复杂场景时,这很重要。如果您的场景很简单(例如,康奈尔盒子),那么差异可以忽略不计。全天跟踪片段着色器中的一些球体。检查http://shadertoy.com/,看看现代GPU和片段着色器可以实现的疯狂。

但是。如果场景和阴影非常复杂,则需要来控制工作的完成方式。渲染一个四边形并在一个碎片着色器中进行跟踪,最多会使你的应用程序挂起,同时驱动程序会哭,改变其合法名称,并移动到世界的另一端......最糟糕的是,崩溃驱动程序。如果单个操作花费的时间过长,很多驱动程序都会中止(这在标准使用情况下几乎不会发生,但是当您开始尝试跟踪1M多边形场景时会很快发生。)

所以你在frag shader中做了太多的工作......下一个逻辑呢?好的,限制工作量。绘制较小的四边形以控制您一次跟踪的屏幕数量。或者使用glScissor。使工作负载越来越小,直到您的驱动程序可以处理它。

猜猜我们刚刚重新发明了什么?计算着色器工作组!工作组是控制作业大小的计算着色器机制,它们比片段级hackery更好的抽象(当我们处理这个时)一种复杂的任务)。现在我们可以非常自然地控制我们发送的光线数量,并且我们可以在不与屏幕空间紧密耦合的情况下实现这一点。对于简单的跟踪器,这会增加不必要的复杂性。对于一个真实的'一,这意味着我们可以轻松地在抖动的网格上进行亚像素光线投射,如果我们愿意的话,可以在每个像素的大量光线投影中进行路径追踪等。

计算着色器的其他功能对于高性能的工业级跟踪器非常有用:

    线程组之间的
  • 共享内存(允许,例如,数据包跟踪,其中同时跟踪整个空间相干光线数据包以利用内存一致性&与附近光线通信的能力)
  • Scatter Writes 允许计算着色器写入任意图像位置(注意:图像和纹理在细微方面有所不同,但优势仍然相关);您不再需要直接从已知像素位置进行跟踪

通常,现代GPU的架构旨在使用计算更自然地支持此类任务。就个人而言,我已经使用MLT,kd树加速和许多其他计算上昂贵的技术(PT已经非常昂贵)编写了实时渐进路径跟踪器。我试图尽可能长时间保持片段着色器/全屏四边形。一旦我的场景足够复杂,需要一个加速结构,我的司机开始窒息,无论我拉什么hackery。我在CUDA中重新实现(与计算不同,但利用相同的基础GPU架构进步),并且全世界都很好。

如果你真的想深入了解,请看一下3.1节:https://graphics.cg.uni-saarland.de/fileadmin/cguds/papers/2007/guenther_07_BVHonGPU/Guenter_et_al._-_Realtime_Ray_Tracing_on_GPU_with_BVH-based_Packet_Traversal.pdf。坦率地说,这个问题的最佳答案将是对GPU微架构的广泛讨论,而且我根本没有资格提供这个。查看上面的现代GPU跟踪文件将让您了解性能考虑的深度。

最后一点:在光线跟踪复杂场景的上下文中,计算优于frag的任何性能优势与光栅化/顶点着色器开销/混合操作开销等完全无关。对于具有复杂着色的复杂场景,跟踪计算中的瓶颈完全,如上所述, compute 着色器具有更高效实施的工具