OpenGL统一缓冲区混淆

Rob*_*son 6 opengl

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

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

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

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

Nic*_*las 11

  1. 为什么你想要?就个人而言,除非你有严重的数据短缺问题并且需要每个字节,否则我认为没有理由使用除了之外的任何东西std140.这使得代码这么干净多了.

    但是,如果您已经死定std140,请继续阅读.

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

    正好有3场布局预选赛:packed,shared,和std140.packed意味着实现可以随意安排所有内容.这包括删除当前程序不使用的制服.因此布局是实现定义的,并且该布局中的某些制服可能已被优化掉.

    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是将统一缓冲区绑定到的统一缓冲区绑定点.

    看到?完全相同的.他们使用不同的术语,但从结构上讲,它们是相同的.如果您需要图片,那么您可以在此处找到包含图表更全面的讨论.