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

Sim*_*ler 6 opengl graphics raytracing compute-shader fragment-shader

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

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

Jos*_*ell 7

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

答案很长:

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

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

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

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

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

  • 线程组之间的共享存储器(例如,允许数据包跟踪,其中同时跟踪整个空间相干光线包以利用存储器一致性和与附近光线通信的能力)
  • 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的任何性能优势与光栅化/顶点着色器开销/混合操作开销等完全无关.对于具有复杂着色的复杂场景,瓶颈完全在跟踪计算中,如所讨论的,计算着色器具有更有效实现的工具.