在OpenGL中`glEnableVertexAttribArray(GLuint index)`的目的是什么?

时间:2016-09-01 06:39:14

标签: opengl opengl-es glsl

调用glVertexAttribPointer(GLuint index, ...)后,默认情况下禁用顶点属性,因为docs

  

默认情况下,禁用所有客户端功能,包括所有通用顶点属性数组。

为什么我们必须使用额外功能启用它?有人可以为案例命名,这有用吗?

在研究时我学到了以下内容:

  • 通过在GLSL或layout(location = x)中使用glBindAttribLocation限定符,我们可以显式设置位置,而不是让OpenGL生成它。但这不是我的问题。

  • glEnableVertexAttribArray不能用于绘制具有多个着色器的一个VAO。当使用程序对象查询属性位置时,可以假设位置是着色器特定的;然后我们可以预料,我们可以在运行正确的着色器之前启用正确的属性位置。但是,我注意到,在测试时,一个位置值可以在不同的着色器中出现多次;此外,输出看起来不对。如果您希望查看代码,请询问。

  • 属性位置存储在VAO中。

2 个答案:

答案 0 :(得分:6)

记住GL已经从一个已有20多年历史的基础API发展而来,为了向后兼容而保留了大量的东西,包括涉及绑定和状态启用的编程风格。

今天的硬件与API的原始硬件完全不同,因此在许多情况下没有明智的“为什么” - 这就是API的工作原理。因此,移动新的Vulkan API会丢弃所有遗留支持,并且具有非常不同的编程模型......

  

为什么我们必须使用额外功能启用它?

...因为这就是API的工作原理。

  

有人可以为案例命名,这有用吗?

...如果你没有启用它就行不通,所以我怀疑它算是有用的。

  

属性位置存储在VAO中。

原始API中不存在VAO;他们后来出现了,实际上他们只是为VBO缓存现有的attribarray设置,所以你仍然需要这个API来设置VAO中引用的内容。

如果你用OpenGL问“为什么”很多你会疯了 - 从程序员模型的角度来看,它不是一个非常“干净”的API,并且在多次迭代中进化,同时在许多情况下保持向后兼容性。有多种做事方式,如果你尝试同时使用两种方式,那么很多事情都没有意义。在大多数情况下,如果没有找到20年前设计原始API时有人在想什么,就不可能准确回答“为什么”。

但是,您可以想象一个理论用例,其中单独的启用很有用。例如,对渲染具有5个属性数组的模型的情况进行成像,然后对具有4个属性数组的不同模型进行成像。对于第二个模型,硬件对第5个属性有什么作用?天真地,它可能会将其复制到GPU中,因此软件需要告诉硬件不要这样做。您可以使用API​​编写特殊属性(例如,NULL指针,长度为零),或者您有一个带有启用设置的API,它只是告诉硬件不要读取内容。

假设启用可能只是寄存器中的位掩码,那么启用驱动程序实际上比必须解码特殊情况顶点属性更有效。

答案 1 :(得分:6)

设置完全合理。启用和禁用它们都有非常有效的用例。

入口点的名称已经强烈暗示了为什么会这样。请注意Array中的glEnableVertexAttribArray()部分。此调用不会“启用该属性”。它允许使用数组中的顶点属性值,这意味着:

  • 如果启用,则每个顶点使用一个与数组分开的值。
  • 如果禁用,则属性的当前值将用于所有顶点。

通过调用glVertexAttrib[1234]f()系列来设置属性的当前值。要在下一次绘制调用中为所有顶点使用相同属性值的用例的典型代码序列是:

glDisableVertexAttribArray(loc);
glVertexAttrib4f(loc, colR, colG, colB, colA);

与每个顶点从数组中获取自己的属性值的情况相比:

glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, ...);

现在,从数组中获取属性肯定更为常见。因此,你可以争辩说,默认情况下使用现代OpenGL是不幸的。但是设置和改变它的要求肯定仍然非常有用。