与常规缓冲区和制服相比,OpenGL纹理单元背后的原因是什么?

时间:2017-08-27 15:08:54

标签: c++ opengl

我是OpenGL API的新手,刚刚发现了纹理以及如何使用它们。生成的纹理缓冲区的绑定方式与绑定常规制服的方式不同,而是使用glActiveTexture,然后使用绑定,而不是仅通过glUniform将纹理提供给着色器,就像我们对其他常量一样

这个惯例背后的原因是什么?

我能想到的唯一原因是利用显卡的全部潜力和纹理处理能力,而不仅仅是直接绑定缓冲区。这是正确的推理,还是仅仅是API的实现方式?

官方维基上没有任何推理,只是说它很奇怪:"用于OpenGL的绑定纹理有点奇怪" https://www.khronos.org/opengl/wiki/Texture

2 个答案:

答案 0 :(得分:5)

您的问题可以通过两种方式解释。

"为什么我们将纹理绑定到上下文而不是着色器?"

因为这会让多个着色器使用相同的纹理变得不必要。请注意,几乎没有图形API直接将纹理附加到程序。不是任何版本的D3D,不是Metal,甚至也不是Vulkan。

纹理是着色器使用的资源。但它们不是着色器的一部分。

"为什么我们将纹理与一般值数组区别对待?"

在现代OpenGL中,着色器可以访问几种不同类型的资源:UBO,SSBO,纹理和图像。这些资源中的每一种最终都代表了图形硬件的潜在不同部分。

存储块不仅仅是一个可以更大的统一块。存储缓冲区表示着色器执行全局内存访问,而统一块通常直接复制到着色器执行单元中。在后一种情况下,访问他们的数据要快得多,但这也意味着您受到执行单元可以拥有的存储量的限制。

现在,并非所有硬件都是如此(AMD的GCN硬件几乎完全相同,这就是为什么their UBO limits are so large)。但是很多硬件也是如此。

纹理甚至更复杂,因为实现需要能够出于性能原因以最佳方式存储数据。因此,纹理存储格式是不透明的。他们甚至在表面上的低级API(如Vulkan)中也不透明。哦,当然,存在线性格式,但是根本不需要实现它们。

因此纹理不仅仅是常数数组。

答案 1 :(得分:1)

你正在比较两个完全不同的东西

纹理对象可以(某种方式)与缓冲对象进行比较。纹理由cardviewglActiveTexture的组合绑定到纹理单元,而缓冲区由glBindTexture绑定,类似于类似的。

纹理采样器均匀在着色器中是均匀的,因此应与其他制服进行比较。此采样器 glBindBuffer调用设置。