Opengl 绘制一组由CUDA/OpenCL生成的元素?

Opengl 绘制一组由CUDA/OpenCL生成的元素?,opengl,cuda,Opengl,Cuda,我是图形编程新手,需要为我们正在创建的演示添加渲染后端。我希望你们能给我指出正确的方向 Short version:是否有任何方法可以向OpenGL发送不同元素的数据数组,而不必为每个元素发出绘制命令 Long version:我们有一个CUDA程序(最终将成为OpenCL),它为我们计算一组对象的一组数据。然后,我们需要使用OpenGL等工具渲染这些对象 CUDA内核可以生成我们的顶点,使用OpenGL interop,它可以将这些顶点放入OpenGL VBO中,而不必将数据传输回主机设备内存

我是图形编程新手,需要为我们正在创建的演示添加渲染后端。我希望你们能给我指出正确的方向

Short version:是否有任何方法可以向OpenGL发送不同元素的数据数组,而不必为每个元素发出绘制命令

Long version:我们有一个CUDA程序(最终将成为OpenCL),它为我们计算一组对象的一组数据。然后,我们需要使用OpenGL等工具渲染这些对象

CUDA内核可以生成我们的顶点,使用OpenGL interop,它可以将这些顶点放入OpenGL VBO中,而不必将数据传输回主机设备内存。但问题是我们有一群(我们的目标是超过一百万)不同的对象。似乎我们在这里的最佳选择是分配一个VBO并将每个对象的顶点放入其中。然后我们可以使用VBO中每个元素的偏移量和长度调用glDrawArrays

但是,每个对象可能有不同数量的顶点(尽管场景中的总顶点可以是有界的。)我希望避免在每帧从CUDA->CPU传输一个开始索引和长度列表,特别是考虑到这些绘制命令将直接返回到GPU

有没有办法用数据打包一个缓冲区,这样我们就可以只调用一次OpenGL来呈现缓冲区,并且它可以呈现该缓冲区中的许多不同元素


(希望我也提供了足够的信息来避免出现XY问题。)

可能不是最优的,但您可以在整个缓冲区上创建一个glDrawArray

  • 如果使用GL_三角形,可以用零填充缓冲区,并且只在内核中写入所需的顶点。这样,缓冲区的“空”区域将绘制为0区域多边形(=退化多边形->根本不绘制)
  • 如果使用GL_TRIANGLE_STRIP,也可以这样做,但必须复制第一个顶点,以便在(0,0,0)和网格之间生成假三角形
这似乎有些过分,但: -无论如何,您必须能够处理尽可能多的顶点 -退化三角形不使用填充率,因此它们几乎是自由的(尽管顶点着色器仍在计算中)


一个可能更好的解决方案是使用gl抽屉元素:在内核中,还可以为整个缓冲区生成索引列表,这将能够完全跳过缓冲区的区域。

一种方法是避免将这些区域理解为单个对象,并使它们成为通过单个绘制调用绘制的单个大型对象。问题是,是什么数据将对象彼此区分开来,这意味着在对
glDrawArrays/glDrawElements
的单独调用之间更改了什么

如果它是一些简单的东西,比如颜色,那么为它提供一个额外的逐顶点属性可能会更容易。通过这种方式,您可以使用单个绘制调用将所有对象渲染为一个大对象,并将各个子对象(实际上现在仅在概念上存在)正确着色。附加属性的内存开销可能非常值得

如果它稍微复杂一点(比如纹理),您仍然可以使用附加的逐顶点属性对其进行索引,可以是纹理数组的索引(因为CUDA/OpenCL支持的硬件应该支持纹理数组),也可以是单个大纹理的特定子区域的纹理坐标(所谓的纹理图谱)

但是,如果这些对象之间的差异更复杂,例如不同的着色器或其他东西,那么您可能确实需要渲染单个对象并进行单独的绘制调用。但是您仍然不需要往返CPU。使用扩展(我认为这是GL 4.0以来的核心,但可能在GL 3硬件(因此CUDA/CL硬件)上受支持,我不知道)您可以从附加缓冲区(您可以像任何其他GL缓冲区一样使用CUDA/CL写入缓冲区)向
glDrawArrays/GLDraweElements
调用提供参数来源。因此,您可以在GPU上组合每个单独对象的偏移长度信息,并将其存储在单个缓冲区中。然后,您可以将
glDrawArraysIndirect
循环偏移到该单个绘制间接缓冲区中(各个对象之间的偏移现在保持不变)



但是,如果发出多个绘制调用的唯一原因是您希望将对象渲染为单个
GL\u三角形条带
s或
GL\u三角形
s(或者,上帝注意,
GL\u多边形
s),您可能需要重新考虑仅使用一组
GL_三角形
,以便可以在单个绘制调用中渲染所有对象使用三角形条带节省的时间和内存可能会被多次绘制调用的开销所抵消,尤其是在渲染许多小三角形条带时。如果确实要使用条带或扇形,可能需要引入退化三角形(通过重复顶点)将它们彼此分离,即使在使用单个绘制调用绘制时也是如此。或者您可以查看GL 3.1引入的函数。

定义“元素”。您说您正在使用
glDrawArrays
命令来渲染它。您正在渲染
GL\u TRIANGLE\u STRIP
s、
GL\u TRIANGLE\u STRIP
,还是其他什么?您渲染的是什么原语?另外,如果您在一个绘制调用中渲染它们,那么此时将无法在对象之间进行任何状态更改。GL\u TRIANGLE\u STRIP(尝试绘制二维“甜甜圈”的分段,如中所示)。但我们希望将其推广到将来绘制任意元素。ARB_draw_indirect看起来正是我所要的!谢谢!我需要确保我们的平台支持扩展(我们最终希望以WebCL为目标,它看起来不支持它,但我们可能能够