glVertexAttribDivisor和glVertexBindingDivisor有什么区别?

时间:2018-06-01 20:14:28

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

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

  

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

(强调我的)

对我来说,似乎答案是声称我可以分割顶点数而不是实例数。但是,当我查看glVertexBindingDivisor的文档并将其与glVertexAttribDivisor进行比较时,它们似乎都指的是发生在实例上的部门而不是顶点。例如,在glVertexBindingDivisor的文档中,它指出:

  

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

(强调我的)

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

2 个答案:

答案 0 :(得分:5)

好的,首先是一个小故事。

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

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

但是由于顶点格式和缓冲区绑定现在是分开的glVertexAttribPointer也相当于说索引index的顶点格式从缓冲区中获取数据索引index处的绑定。这很重要,因为这不是自动的; 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并没有做到最后一部分。

答案 1 :(得分:2)

  

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

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

使用ARB_vertex_attrib_binding(自GL 4.3以来的核心),引入了一个新的API,它将顶点格式与指针分开。期望切换数据指针是快速的,而切换顶点格式可能更昂贵。新API允许分别显示两个方面,而旧API始终同时设置两个方面。

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