调用glDisableVertexAttribArray()很重要吗?

Gru*_*rig 52 opengl-es webgl vertex-shader

我不完全清楚启用顶点属性数组的范围.我有几个不同的着色器程序,它们具有不同数量的顶点属性.是glEnableVertexAttribArray对着色器程序本地调用还是全局调用?

现在我在创建着色器程序时启用顶点属性数组,并且从不禁用它们,并且一切似乎都有效,但似乎我可能应该在绘制调用之前/之后启用/禁用它们.对此有影响吗?

(我正在使用WebGL,所以我们真的在谈论gl.enableVertexAttribArraygl.disableVertexAttribArray.我还会注意到橙皮书,OpenGL着色语言,对这些调用没有任何信息.)

dat*_*olf 42

启用顶点属性数组的状态可以绑定到顶点数组对象(VAO),也可以是全局的.

如果您使用VAOs,那么你应该不会禁用属性阵列,它们封装在VAO.

但是对于全局顶点属性数组启用状态,您应该禁用它们,因为如果它们被启用,OpenGL将尝试从数组中读取,这些数组可能绑定到无效指针,如果指针指向客户端地址,可能会使程序崩溃空格,或者如果它指出了绑定的顶点缓冲区对象的限制,则引发OpenGL错误.

  • @Grumdrig:问题是另一个问题.用着色器1说你有属性A和B,每个有500个顶点.然后切换到仅具有属性A的着色器2,但这次绘制1000个顶点.如果你没有禁用属性B,OpenGL会尝试从B的缓冲区中读取1000个顶点,如果不是未绑定,则更改或禁用B将是B中仅有的500个属性的超出范围访问权限. (8认同)
  • @Dreamer:gman并不是指"顶点数组对象",而是"顶点缓冲对象",这是WebGL的要求.不幸的是他的命名法已经过时了.他的意思是,WebGL不支持客户端侧顶点数组,即将客户端地址空间传递给glVertexAttribPointer函数.在WebGL和OpenGL-3.3及更高版本的核心配置文件中,您必须将顶点数据放在服务器端的顶点缓冲区对象中.这就是他的意思. (2认同)

gma*_*man 14

WebGL与OpenGL不同.

在WebGL中,只要连接到属性的缓冲区和(a)如果使用它足够大以满足绘制调用或(b)它未被使用,则允许显式启用数组.

与OpenGL ES 2.0不同,WebGL不允许客户端阵列.

证明:

var gl = document.querySelector("canvas").getContext("webgl");
var m4 = twgl.m4;
var programInfo2Attribs = twgl.createProgramInfo(gl, ["vs-uses-2-attributes", "fs"]);
var programInfo1Attrib  = twgl.createProgramInfo(gl, ["vs-uses-1-attribute", "fs"]);

var arrays2Attribs = {
  position: [
    -1, -1, 0, 
    1, -1, 0, 
    -1, 1, 0, 
  ],
  color: [
    1,0,0,1,
    1,1,0,1,
    0,1,0,1,
  ],
};

var arrays1Attrib = {
  position: [
    -1, -1, 0, 
    1, -1, 0, 
    -1, 1, 0, 
    -1, 1, 0, 
    1, -1, 0, 
    1, 1, 0,
  ],
};


var bufferInfo2Attribs = twgl.createBufferInfoFromArrays(gl, arrays2Attribs);
var bufferInfo1Attrib  = twgl.createBufferInfoFromArrays(gl, arrays1Attrib);

var uniforms = {
  u_matrix: m4.scale(m4.translation([-0.5, 0, 0]), [0.25, 0.5, 0.5]),
};

gl.useProgram(programInfo2Attribs.program);
twgl.setBuffersAndAttributes(gl, programInfo2Attribs, bufferInfo2Attribs);
twgl.setUniforms(programInfo2Attribs, uniforms);
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo2Attribs);

uniforms.u_matrix = m4.scale(m4.translation([0.5, 0, 0]), [0.25, 0.5, 0.5]);

gl.useProgram(programInfo1Attrib.program);
twgl.setBuffersAndAttributes(gl, programInfo1Attrib, bufferInfo1Attrib);
twgl.setUniforms(programInfo1Attrib, uniforms);
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo1Attrib);
Run Code Online (Sandbox Code Playgroud)
canvas { border: 1px solid black; }
Run Code Online (Sandbox Code Playgroud)
<script src="https://twgljs.org/dist/twgl-full.min.js"></script>
<script id="vs-uses-2-attributes" type="not-js">
attribute vec4 position;
attribute vec4 color;
  
varying vec4 v_color;

uniform mat4 u_matrix;
  
void main() {
  gl_Position = u_matrix * position;
  v_color = color;
}
</script>
<script id="vs-uses-1-attribute" type="not-js">
attribute vec4 position;
  
varying vec4 v_color;
  
uniform mat4 u_matrix;
  
void main() {
  gl_Position = u_matrix * position;
  v_color = vec4(0,1,0,1);
}
</script>
<script id="fs" type="not-js">
precision mediump float;
varying vec4 v_color;

void main() {
  gl_FragColor = v_color;
}
</script>
<p>
1st it draws a triangle (3 vertices, 2 attributes)<br/>
2nd it draws a quad (6 vertices, 1 attribute)<br/>
It does NOT called gl.disableVertexAttrib so on the second draw call one of the attributes is still enabled. It is pointing to a buffer with only 3 vertices in it even though 6 vertices will be drawn. There are no errors.
</p>
<canvas></canvas>
Run Code Online (Sandbox Code Playgroud)