使用opengl将每像素绘制成后备缓冲区或纹理以显示到屏幕 - 没有glDrawPixels()

时间:2011-05-19 02:38:56

标签: arrays opengl textures render-to-texture

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

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

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

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

是什么让你认为着色器会出现问题?着色器的整体思想是非常非常快速地处理大量数据。请在搜索短语“General Purpose GPU computing”或“GPGPU”上使用Google。

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

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

答案 2 :(得分:0)

  

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

一个好方法是尽量避免任何不必要的额外副本。因此,您可以使用Pixel Buffer Objects map to your address space,并使用该buffer object streaming直接生成您的数据。

由于您希望每帧更新此数据,因此您还希望寻找高效的{{3}},这样您就不会强制CPU和GPU之间的隐式同步。在您的场景中,一种简单的方法是使用3个PBO的环形缓冲区,您可以在每个帧中前进。

  

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

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

嗯,驱动程序所做的完全是针对特定于实现的。我不认为"每次都会导致中断"这是一个有用的心理形象。您似乎完全低估了GL实施背后的工作。 GL调用与发送给GPU的某些命令不对应。

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

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

你完全错了。没有办法使用着色器。如果您不是自己编写一个(例如使用旧的"固定功能管道和GL的#34;),GPU驱动程序将为您提供着色器。这些早期固定功能阶段的硬件实现已完全被可编程单元取代 - 因此,如果您无法使用着色器,则无法使用GPU执行此操作。我强烈建议您编写自己的着色器(无论如何,它是现代GL中的唯一选项)。