1

基本上,我有一组数据(流体模拟数据),这些数据是从用户输入(从系统内存中开始)实时生成的。我想将流体的密度作为 alpha 值写入纹理 - 我对数组值进行插值以生成屏幕大小的数组(网格相对较小)并将其映射到 0 - 255 范围。将这些值写入纹理以供使用的最有效方法(ogl 函数)是什么?

其他地方建议的东西,我认为我不想使用(如果我弄错了,请告诉我):

  1. glDrawPixels() - 我的印象是每次调用它都会导致中断,这会使其变慢,尤其是在高分辨率下。

  2. 使用着色器 - 我不认为着色器可以接受和处理每帧数组中的数据量(在别处提到他们可能接受的数据量上限太低)

4

3 回答 3

2

如果我正确理解您的问题,那么这两种解决方案都会使问题过于复杂。我是否认为您已经生成了一个大小为 x*y 的数组,其中 x 和 y 是您的屏幕分辨率,填充了无符号字节?

如果是这样,如果您想要使用此数据作为其 alpha 通道的 OpenGL 纹理,为什么不创建一个纹理,将其绑定到 GL_TEXTURE_2D 并使用您的数据调用glTexImage2D,使用 GL_ALPHA 作为格式和内部格式,使用 GL_UNSIGNED_BYTE 作为类型和(x,y) 作为大小?

于 2011-05-19T08:25:51.030 回答
2

是什么让您认为着色器会表现不佳?着色器的整个想法是非常非常快速地处理大量数据。请使用 Google 搜索词组“通用 GPU 计算”或“GPGPU”。

着色器只能从缓冲区收集数据,不能分散。但他们能做的是改变缓冲区中的值。这允许(片段)着色器写入 *GL_POINT*s 的位置,然后依次放置在纹理的目标像素上。Shader Model 3 和更高版本的 GPU 还可以从几何和顶点着色器阶段访问纹理采样器,因此片段着色器部分变得非常简单。

如果您只有位置和值的线性流,只需通过顶点数组将它们发送到 OpenGL,绘制 *GL_POINT*s,目标纹理是帧缓冲区对象的颜色附件。

于 2011-05-19T10:17:40.513 回答
0

将这些值写入纹理以供使用的最有效方法(ogl 函数)是什么?

一个好方法是尽量避免任何不必要的额外副本。因此,您可以使用映射到地址空间的像素缓冲区对象,并使用它直接将数据生成到其中。

由于您希望每帧更新此数据,因此您还希望寻找有效的缓冲区对象流,这样您就不会强制 CPU 和 GPU 之间的隐式同步。在您的场景中执行此操作的一种简单方法是使用 3 个 PBO 的环形缓冲区,您每帧都将其推进。

其他地方建议的东西,我认为我不想使用(如果我弄错了,请告诉我):

  1. glDrawPixels() - 我的印象是每次调用它都会导致中断,这会使其变慢,尤其是在高分辨率下。

好吧,驱动程序所做的完全是特定于实现的。我不认为“每次都造成中断”在这里是有用的心理形象。您似乎完全低估了 GL 实施将在您背后做的工作。GL 调用不会对应于发送到 GPU 的某些命令。

但不使用glDrawPixels仍然是一个不错的选择。它不是很有效,并且已被弃用并从现代 GL 中删除。

  1. 使用着色器 - 我不认为着色器可以接受和处理每帧数组中的数据量(在别处提到他们可能接受的数据量上限太低)

你完全错了。没有办法使用着色器。如果您不是自己编写的(例如,通过使用 GL 的旧“固定功能管道”),GPU 驱动程序将为您提供着色器。这些早期固定功能阶段的硬件实现已经完全被可编程单元取代——所以如果你不能用着色器来做,你就不能用 GPU 来做。而且我强烈建议您编写自己的着色器(无论如何,它是现代 GL 中的唯一选择)。

于 2016-08-13T10:10:39.533 回答