【问题标题】:What is the difference between glVertexAttribDivisor and glVertexBindingDivisor?glVertexAttribDivisor 和 glVertexBindingDivisor 有什么区别?
【发布时间】:2018-06-01 20:14:28
【问题描述】:

我一直在寻找将属性与任意顶点分组相关联的方法,起初实例化似乎是我完成此任务的唯一方法,但后来我偶然发现了 this questionthis answer 状态:

然而,较新版本的 OpenGL 可以设置某个顶点属性的缓冲区偏移前进的速率。实际上,这意味着给定顶点数组的数据在属性的缓冲区偏移量增加之前复制到 n 个顶点。设置这个除数的函数是glVertexBindingDivisor

(强调我的)

在我看来,答案似乎是我可以根据顶点数而不是实例数进行划分。但是,当我查看 glVertexBindingDivisor 的文档并将其与 glVertexAttribDivisor 的文档进行比较时,它们似乎都指的是发生在 instances 而不是 vertices 上的划分.例如在glVertexBindingDivisor 的文档中它指出:

glVertexBindingDivisor 和 glVertexArrayBindingDivisor 修改在单个绘制命令中渲染多个 实例 图元时通用顶点属性的前进速率。如果除数为零,则使用绑定到 bindingindex 的缓冲区的属性每个顶点都会前进一次。如果除数不为零,则属性会在被渲染的顶点集的每个除数实例中前进一次。如果相应的除数不为零,则属性称为instanced

(强调我的)

那么这两个函数之间的实际区别是什么?

【问题讨论】:

    标签: opengl vertex opengl-4 vertex-buffer vertex-attributes


    【解决方案1】:

    好的,首先是一些背景故事。

    从 OpenGL 4.3/ARB_vertex_attrib_binding(又名:glVertexBindingDivisor 来自哪里,所以这是相关的),VAO 在概念上分为两部分:描述单个属性的数据价值的顶点格式数组和数组描述如何获取数据数组的缓冲区绑定点(缓冲区对象、偏移量、步幅和除数)。顶点格式指定其数据来自哪个缓冲区绑定点,以便多个属性可以从同一个数组中获取数据(即:交错)。

    当 VAO 被分成这两部分时,旧的 API 会根据新系统进行重新定义。因此,如果您使用属性索引调用glVertexAttribPointer,此函数将设置给定index 格式的顶点格式数据,并将设置缓冲区绑定状态(缓冲区对象、字节偏移等)为相同的index。现在,这是两个独立的 VAO 状态数据数组(顶点格式和缓冲区绑定);这个函数只是在两个数组中使用相同的索引。

    但是由于顶点格式和缓冲区绑定现在是分离的,glVertexAttribPointer 也相当于说索引index 处的顶点格式从索引@ 处的缓冲区绑定中获取数据987654327@。这很重要,因为这不是自动的。 vertex_attrib_binding 的全部意义在于一个索引处的顶点格式可以使用来自不同索引的缓冲区绑定。因此,当您使用旧 API 时,它会通过将格式 index 链接到绑定 index 来将自己重置为旧行为。

    现在,所有这些与除数有什么关系?好吧,因为我刚才说的那件事实际上是他们之间的唯一区别。

    glVertexAttribDivisor 是用于设置除数的老式 API。它需要一个属性索引,但它作用于作为缓冲区绑定点一部分的状态(实例化是每个数组的构造,而不是现在的每个属性构造)。这意味着该函数假定(在新系统中)index 处的属性从index 处的缓冲区绑定点获取其数据。

    而且我刚才说的有点谎言。它通过直接设置顶点格式以使用该缓冲区绑定点强制这个“假设”。也就是说,它与glVertexAttribPointer 执行的最后一步相同。

    glVertexBindingDivisor 是现代功能。它没有传递属性索引;它传递了一个缓冲区绑定索引。因此,它不会更改属性的缓冲区绑定索引。

    所以glVertexAttribDivisor 完全等价于:

    void glVertexAttribDivisor(GLuint index, GLuint divisor)
    {
      glVertexBindingDivisor(index, divisor);
      glVertexAttribBinding(index, index);
    }
    

    显然,glVertexBindingDivisor 没有做最后一部分。

    【讨论】:

      【解决方案2】:

      那么这两个函数的实际区别是什么?

      现代 OpenGL 有 两个 用于指定顶点属性数组及其属性的不同 API。传统的glVertexAttribArray 和朋友,glVertexAttribDivisor 也是其中的一部分。

      ARB_vertex_attrib_binding(自 GL 4.3 起在核心中)引入了一个新的 API,它将顶点格式与指针分开。预计切换数据指针会很快,而切换顶点格式可能会更昂贵。新的 API 允许明确地分别控制这两个方面,而旧的 API 总是同时设置这两个方面。

      对于新的 API,引入了一个新层:缓冲区绑定点。 (有关详细信息,请参阅 OpenGL wiki。)glVertexBindingDivisor 为此类绑定点指定属性实例化除数,因此它在概念上等同于新 API 的 glVertexAttribDivisor 函数。

      【讨论】:

      • 呵呵,我是否错过了我当时链接的答案?还是他们刚才弄错了?
      猜你喜欢
      • 2010-10-02
      • 2011-12-12
      • 2010-09-16
      • 2012-03-14
      • 2012-02-06
      • 2011-02-25
      • 2011-11-22
      • 2015-03-26
      • 2013-08-19
      相关资源
      最近更新 更多