当前有4种方法可以执行此操作:标准1D纹理,缓冲区纹理,统一缓冲区和着色器存储缓冲区。
一维纹理
使用此方法,您可以glTex(Sub)Image1D
用数据填充一维纹理。由于您的数据只是浮点数的数组,因此您的图片格式应为GL_R32F
。然后,您可以通过简单的texelFetch
调用在着色器中对其进行访问。texelFetch
获取texel坐标(因此命名),并关闭所有过滤。因此,您得到的正是一个纹理像素。
注意:texelFetch
是3.0+。如果要使用以前的GL版本,则需要将尺寸传递给着色器并手动规范化纹理坐标。
这里的主要优点是兼容性和紧凑性。这将在GL 2.1硬件上运行(使用表示法)。而你不具备在使用GL_R32F
格式; 您可以使用GL_R16F
半浮点数。或者,GL_R8
如果您的数据对于标准化字节是合理的。尺寸对于整体性能可能意义重大。
主要缺点是尺寸限制。您只能使用最大纹理大小的一维纹理。在GL 3.x级硬件上,此值约为8,192,但保证不低于4,096。
统一缓冲区对象
这种工作方式是在着色器中声明一个统一块:
layout(std140) uniform MyBlock
{
float myDataArray[size];
};
然后,您可以像在数组中一样在着色器中访问该数据。
返回C / C ++ / etc代码,您将创建一个缓冲区对象,并用浮点数据填充它。然后,您可以将该缓冲区对象与MyBlock
统一块关联。更多详细信息可以在这里找到。
该技术的主要优点是速度和语义。速度归因于实现与纹理相比如何处理统一缓冲区。纹理提取是全局内存访问。统一缓冲区访问通常不是;当着色器在渲染时初始化时,统一缓冲区数据通常会加载到着色器中。从那里开始,它是本地访问,速度更快。
从语义上讲,这是更好的方法,因为它不仅仅是平面数组。对于您的特定需求,如果您只需要一个float[]
,就没有关系了。但是,如果您具有更复杂的数据结构,则语义可能很重要。例如,考虑一个灯光阵列。灯光具有位置和颜色。如果使用纹理,则用于获取特定光源的位置和颜色的代码如下所示:
vec4 position = texelFetch(myDataArray, 2*index);
vec4 color = texelFetch(myDataArray, 2*index + 1);
使用统一缓冲区,它看起来就像其他统一访问一样。您已经命名了可以称为position
和的成员color
。这样所有的语义信息就在那里。更容易了解正在发生的事情。
也有大小限制。OpenGL要求实现为统一块的最大大小提供至少16384个字节。这意味着,对于浮点数组,您只能得到4,096个元素。再次注意,这是实现所需的最低要求;一些硬件可以提供更大的缓冲区。例如,AMD在其DX10级硬件上提供65,536。
缓冲区纹理
这些是一种“超级1D纹理”。它们有效地允许您从纹理单元访问缓冲区对象。尽管它们是一维的,但它们不是一维纹理。
您只能在GL 3.0或更高版本中使用它们。而且您只能通过texelFetch
功能访问它们。
这里的主要优点是尺寸。缓冲区纹理通常可以非常庞大。尽管规范通常是保守的,规定缓冲区纹理至少为65,536字节,但大多数GL实现方案都允许它们的大小范围为兆字节。实际上,通常最大大小通常受可用GPU内存的限制,而不是硬件限制。
同样,缓冲区纹理存储在缓冲区对象中,而不是更不透明的纹理对象(如1D纹理)中存储。这意味着您可以使用一些缓冲区对象流技术来更新它们。
就像1D纹理一样,这里的主要缺点是性能。缓冲区纹理可能不会比一维纹理慢,但它们也不会像UBO一样快。如果您只是从它们中拉出一个浮标,则不必担心。但是,如果您要从中提取大量数据,请考虑使用UBO。
着色器存储缓冲区对象
OpenGL 4.3提供了另一种处理方式:着色器存储缓冲区。它们很像统一缓冲区。您可以使用几乎与统一块相同的语法来指定它们。原则上的区别在于您可以写信给他们。显然,这对您的需求没有用,但是还有其他差异。
从概念上讲,着色器存储缓冲区是缓冲区纹理的另一种形式。因此,着色器存储缓冲区的大小限制是很多比均匀的缓冲器大。最大UBO大小的OpenGL最小值为16KB。最大SSBO大小的OpenGL最小值为16MB。因此,如果您拥有硬件,它们是UBO的有趣替代品。
请确保将它们声明为readonly
,因为您没有在写信给他们。
相对于UBO,此处的潜在缺点再次是性能。SSBO通过缓冲区纹理像图像加载/存储操作一样工作。基本上,它是imageBuffer
图像类型周围的(非常好)语法糖。因此,从这些读取可能会以从读取的速度执行readonly imageBuffer
。
目前尚不清楚通过图像加载/通过缓冲图像存储读取是否比缓冲纹理更快或更慢。
另一个潜在的问题是,您必须遵守非同步内存访问的规则。这些很复杂,很容易使您绊倒。