opengl - What is the difference between glVertexAttribDivisor and glVertexBindingDivisor?
问题描述
I was looking for ways to associate attributes with arbitrary groupings of verticies, at first instancing appeared to be the only way for me to accomplish this, but then I stumbled up this question and this answer states :
However what is possible with newer versions of OpenGL is setting the rate at which a certain vertex attribute's buffer offset advances. Effectively this means that the data for a given vertex array gets duplicated to n vertices before the buffer offset for a attribute advances. The function to set this divisor is glVertexBindingDivisor.
(emphasis mine)
Which to me seems as if the answer is claiming I can divide on the number of vertices instead of the number of instances. However, when I look at glVertexBindingDivisor
's documentation and compare it to glVertexAttribDivisor
's they both appear to refer to the division taking place over instances and not vertices. For example in glVertexBindingDivisor
's documentation it states:
glVertexBindingDivisor and glVertexArrayBindingDivisor modify the rate at which generic vertex attributes advance when rendering multiple instances of primitives in a single draw command. If divisor is zero, the attributes using the buffer bound to bindingindex advance once per vertex. If divisor is non-zero, the attributes advance once per divisor instances of the set(s) of vertices being rendered. An attribute is referred to as instanced if the corresponding divisor value is non-zero.
(emphasis mine)
So what is the actual difference between these two functions?
解决方案
好的,首先是一些背景故事。
从 OpenGL 4.3/ARB_vertex_attrib_binding(AKA:glVertexBindingDivisor
从哪里来,所以这是相关的),VAO 在概念上分为两部分:描述单个属性数据价值的顶点格式数组,以及描述数据的缓冲区绑定点数组如何获取数据数组(缓冲区对象、偏移量、步幅和除数)。顶点格式指定其数据来自哪个缓冲区绑定点,以便多个属性可以从同一个数组中获取数据(即:交错)。
当 VAO 被分成这两部分时,旧的 API 会根据新系统重新定义。因此,如果您glVertexAttribPointer
使用属性索引调用,此函数将为给定的格式设置顶点格式数据,index
并将设置缓冲区绑定状态(缓冲区对象、字节偏移量等)为相同的index
。现在,这是两个独立的 VAO 状态数据数组(顶点格式和缓冲区绑定);这个函数只是在两个数组中使用相同的索引。
但是由于顶点格式和缓冲区绑定现在是分开的,glVertexAttribPointer
所以也相当于说 index 处的顶点格式从 indexindex
处的缓冲区绑定中获取数据index
。这很重要,因为这不是自动的。vertex_attrib_binding 的全部意义在于一个索引处的顶点格式可以使用来自不同索引的缓冲区绑定。因此,当您使用旧 API 时,它会通过将 format 链接index
到 binding将自身重置为旧行为index
。
现在,所有这些与除数有什么关系?好吧,因为我刚才说的那件事实际上是他们之间的唯一区别。
glVertexAttribDivisor
是用于设置除数的旧式 API。它需要一个属性索引,但它作用于作为缓冲区绑定点一部分的状态(实例化是每个数组的构造,而不是现在的每个属性构造)。这意味着该函数假定(在新系统中)属性 atindex
从缓冲区绑定点 at 获取其数据index
。
而且我刚才说的有点假。它通过直接设置顶点格式以使用该缓冲区绑定点来强制执行此“假设” 。也就是说,它执行与之前相同的最后一步。glVertexAttribPointer
glVertexBindingDivisor
是现代功能。它没有传递属性索引;它传递了一个缓冲区绑定索引。因此,它不会更改属性的缓冲区绑定索引。
所以glVertexAttribDivisor
完全等价于:
void glVertexAttribDivisor(GLuint index, GLuint divisor)
{
glVertexBindingDivisor(index, divisor);
glVertexAttribBinding(index, index);
}
显然,glVertexBindingDivisor
不做最后一部分。
推荐阅读
- ios - 两个故事板连接并一次使用两个设备运行
- react-native - 如何在 Detox 中控制 React-Native webview?
- android - 找不到对应设置java的xml
- git - 如何重置远程分支的提交?
- angular - Angular6 ngModelChange 中的去抖动时间
- java - 如何使用 Java 从 Linux 中的 docx 中获取文本数据和表格数据?
- php - 如何“正则表达式”选择菜单中的所有选项
- javascript - 当数据未定义或为空时如何使用 Lodash
- node.js - 是否有任何 api (nodejs/python) 允许与给定电子邮件共享 google sheet(给定工作表 id)
- nginx - NGINX 上的每个 IP 地址每秒计算请求数