有人能告诉我看似不必要的复杂的制服缓冲区吗?我已经阅读了OpenGL Superbible 5中的部分,我已经在博客上查看了一些示例,并且我已经阅读了官方规范,但我仍然没有得到它。
具体来说,所有示例似乎都需要一个着色器程序,以便最初使用glGetActiveUniformsiv设置统一缓冲区。我不明白这一点。为什么接口不允许您在不参考着色器程序的情况下定义结构,在链接时针对程序验证缓冲区/ s格式?
其次,如果我从一个程序获得结构布局,假设所有使用这套制服的程序的结构布局相同,结构是否保证具有相同的偏移量,数据大小等等?我会这么认为。
第三,我不明白约束点。我必须使用索引调用glBindBufferBase,然后使用块索引调用glUniformBlockBinding,并将索引传递给glBindBufferBase。我无法直观地看到这里发生了什么。 Superbible缺乏清晰度,我见过的规格和样品也是如此。
答案 0 :(得分:11)
为什么你想要?就个人而言,除非您遇到严重的数据短缺问题且需要每个字节,否则我认为没有理由使用std140
以外的任何其他内容。它使代码所以更清洁。
但是,如果你因为避免std140
而死定,请继续阅读。
规范彻底解释了这一点:它都在布局限定符中。
正好有3个布局限定符:packed
,shared
和std140
。 packed
意味着实现可以随意安排所有内容。这包括删除当前程序不使用的制服。因此布局是实现定义的,并且该布局中的某些制服可能已被优化掉。
shared
表示实施可以像packed
一样自由排列数据。但是,必须为每件制服提供存储空间。这使得在程序之间共享统一布局成为可能,因此得名。 shared
还要求实现将为程序之间的一致定义提供一致的布局。因此,您只需要查询一个布局。
要回答您的第一个问题,您可以根据需要使用shared
布局创建虚假程序。您可以使用它来查询统一块的布局。然后,只要布局在其他程序(使用shared
布局)中保持一致,布局都将是相同的。因此,不需要特殊的API。
std140
意味着统一块的布局由OpenGL实现明确定义,逐字节。这隐含地允许共享,因为在该规范下的两个相同的统一块将具有相同的布局。由于实施无法优化std140
布局块中的制服,所以一切都很完美。
同样,几乎没有理由避免std140
。除非您处于非常非常严重的内存限制之下。
完全与纹理相同的机制。唯一的区别是统一的块名称本身不是制服。
纹理对象使用glActiveTexture(GL_TEXTURE0 + i);glBindTexture()
绑定到纹理图像单元,其中i
是纹理图像单元索引。您现在需要告诉着色器哪个采样器使用该图像单元。但是,OpenGL不允许您直接与名称关联;您必须将采样器名称转换为索引位置。因此,您可以使用glGetUniformLocation
为特定采样器提供统一的位置。获得统一位置后,可以通过调用glUniform1i(loc, i)
将纹理图像单元与该位置相关联,其中i
是绑定纹理的纹理图像单元。
使用glBindBufferRange(GL_UNIFORM_BUFFER, i, ...)
将统一缓冲区对象绑定到统一缓冲区绑定点,其中i
是统一缓冲区绑定点。您现在需要告诉着色器哪个统一块使用该绑定点。但是,OpenGL不允许您直接与名称关联;你必须将统一块转换为索引位置。因此,您可以使用glGetUniformBlockIndex
获取特定统一块的索引。获得索引后,可以通过调用glUniformBlockBinding(program, index, i)
将统一缓冲区绑定点与该索引相关联,其中i
是将统一缓冲区绑定到的统一缓冲区绑定点。
请参阅?完全相同的。他们使用不同的术语,但从结构上讲,它们是相同的。如果您需要图片,则可以找到more thorough discussion that includes a diagram here。