|
1
48
启用“顶点属性阵列”的状态可以绑定到顶点阵列对象(VAO),也可以是全局的。 如果你正在使用VAO,那么你应该 不 禁用属性数组,因为它们封装在VAO中。 但是,对于全局顶点属性数组启用状态,您应该禁用它们,因为如果它们保持启用状态,OpenGL将尝试从数组中读取,数组可能绑定到无效指针,如果指针指向客户端地址空间,则可能会导致程序崩溃,或者如果指针超出绑定的顶点缓冲区对象的限制,则会引发OpenGL错误。 |
|
2
15
WebGL与OpenGL不同。 在WebGL中,只要有一个附加到属性的缓冲区,并且(a)如果使用了缓冲区,它的大小足以满足draw调用,或者(b)没有使用缓冲区,就明确允许启用数组。 与OpenGL ES 2.0不同,WebGL不允许客户端阵列。 证明:
另一个例子是,只需启用所有属性,然后使用不使用属性的着色器进行绘制(无错误),还可以使用使用1个属性的着色器(同样无错误)进行绘制,无需调用
|
|
|
3
2
对于webGL,我将采用 对 ,调用gl.disableVertexAttribArray很重要。 Chrome向我发出警告:
当程序更改为使用少于最大属性数的程序时,就会发生这种情况。显然,解决方案是在绘制之前禁用未使用的属性。 如果所有程序都使用相同数量的属性,那么在初始化时调用gl.enableVertexAttribArray一次就可以了。否则,您需要在更改程序时对其进行管理。 |
|
|
4
-2
可以将其视为属性是VAO的本地属性,而不是着色器程序。VBO在GPU存储器中。 现在考虑一下,在WebGL中,有一个WebGL默认使用的默认VAO。(它也可以是程序员创建的VAO,同样的概念也适用)。此VAO包含一个名为ARRAY_BUFFER的目标,GPU内存中的任何VBO都可以绑定到该目标。这个VAO还包含一个具有固定数量的属性槽的属性数组(数量取决于实现和平台,这里假设为8,这是Webgl规范所要求的最小值)。此外,此VAO将具有ELEMENT_ARRAY_BUFFER目标,任何索引数据缓冲区都可以绑定到该目标。 现在,当您创建着色器程序时,它将具有您指定的属性。链接着色器程序时,Webgl将为程序中指定的所有属性指定一个可能的属性槽“数字”。现在属性将使用VAO中的相应属性槽来访问绑定到VAO中ARRAY_BUFFER或ELEMENT_ARRAY_BUFFER目标的数据。现在,当您使用函数gl.enableVertexAttribArray(location)和gl.vertexAttripPointer(location,…)时,您不会更改着色器程序中属性的任何特性(它们只是有一个属性编号,该编号指的是VAO中用于访问数据的属性槽之一)。实际执行的操作是使用VAO中的位置编号修改属性窗的状态。因此,为了使程序中的属性能够访问数据,必须启用VAO中相应的属性槽(gl.enableVertexAttribArray())。我们必须配置属性槽,以便它能够正确地从绑定到ARRAY_buffer的缓冲区读取数据(gl.vertexAttripPointer()),即使我们将其从目标解除绑定,只要它在GPU存储器中,属性槽csn仍然是VBO的红色。此外,必须有一些缓冲区绑定到VAO的目标(gl.bindBuffer())。因此,gl.enableVertexAttribArray(location)将启用当前VAO中由“location”指定的属性槽。gl.disableVertexAttribArray(location)将禁用它。不过它与着色器程序无关。即使使用不同的着色器程序,这些属性槽的状态也不会受到影响。 因此,如果两个不同的着色器程序使用相同的属性槽,则不会出现任何错误,因为VAO中相应的属性槽已经处于活动状态。但是如果在两个着色器程序中需要不同的属性来解释数据,则来自目标的数据可能被错误地读取。现在考虑一下,如果两个着色器程序使用不同的属性槽,那么您可能会启用第二个着色器程序所需的属性槽并认为您的程序应该可以工作。但是已经启用的属性槽(由以前的着色器程序启用)仍将启用,但不会使用。这会导致一个错误。 因此,在更改着色器程序时,我们必须确保VAO中不会被该着色器程序使用的已启用属性槽必须被禁用。尽管我们现在可以显式指定任何VAO,但Webgl默认情况下是这样工作的。 一种方法是在javascript端维护一个已启用属性的列表,并在切换程序时禁用所有已启用的属性槽,同时仍使用相同的VAO。处理此问题的另一种方法是创建仅由一个着色器程序访问的自定义VAO。但效率较低。还有一种方法是在使用gl.bindAttribLocation()链接着色器程序之前,将属性位置绑定到固定槽。 |