OpenGL统一缓冲区混淆

时间:2011-09-09 20:30:35

标签: opengl

有人能告诉我看似不必要的复杂的制服缓冲区吗?我已经阅读了OpenGL Superbible 5中的部分,我已经在博客上查看了一些示例,并且我已经阅读了官方规范,但我仍然没有得到它。

具体来说,所有示例似乎都需要一个着色器程序,以便最初使用glGetActiveUniformsiv设置统一缓冲区。我不明白这一点。为什么接口不允许您在不参考着色器程序的情况下定义结构,在链接时针对程序验证缓冲区/ s格式?

其次,如果我从一个程序获得结构布局,假设所有使用这套制服的程序的结构布局相同,结构是否保证具有相同的偏移量,数据大小等等?我会这么认为。

第三,我不明白约束点。我必须使用索引调用glBindBufferBase,然后使用块索引调用glUniformBlockBinding,并将索引传递给glBindBufferBase。我无法直观地看到这里发生了什么。 Superbible缺乏清晰度,我见过的规格和样品也是如此。

1 个答案:

答案 0 :(得分:11)

  1. 为什么你想要?就个人而言,除非您遇到严重的数据短缺问题且需要每个字节,否则我认为没有理由使用std140以外的任何其他内容。它使代码所以更清洁。

    但是,如果你因为避免std140而死定,请继续阅读。

  2. 规范彻底解释了这一点:它都在布局限定符中。

    正好有3个布局限定符:packedsharedstd140packed意味着实现可以随意安排所有内容。这包括删除当前程序不使用的制服。因此布局是实现定义的,并且该布局中的某些制服可能已被优化掉。

    shared表示实施可以像packed一样自由排列数据。但是,必须为每件制服提供存储空间。这使得在程序之间共享统一布局成为可能,因此得名。 shared还要求实现将为程序之间的一致定义提供一致的布局。因此,您只需要查询一个布局。

    要回答您的第一个问题,您可以根据需要使用shared布局创建虚假程序。您可以使用它来查询统一块的布局。然后,只要布局在其他程序(使用shared布局)中保持一致,布局都将是相同的。因此,不需要特殊的API。

    然而,

    std140意味着统一块的布局由OpenGL实现明确定义,逐字节。这隐含地允许共享,因为在该规范下的两个相同的统一块将具有相同的布局。由于实施无法优化std140布局块中的制服,所以一切都很完美。

    同样,几乎没有理由避免std140。除非您处于非常非常严重的内存限制之下。

  3. 完全与纹理相同的机制。唯一的区别是统一的块名称本身不是制服。

    纹理对象使用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