Is it important to call glDisableVertexAttribArray()?

寵の児 提交于 2019-12-02 17:23:47

The state of which Vertex Attribute Arrays are enabled can be either bound to a Vertex Array Object (VAO), or be global.

If you're using VAOs, then you should not disable attribute arrays, as they are encapsulated in the VAO.

However for global vertex attribute array enabled state you should disable them, because if they're left enabled OpenGL will try to read from arrays, which may be bound to a invalid pointer, which may either crash your program if the pointer is to client address space, or raise a OpenGL error if it points out of the limits of a bound Vertex Buffer Object.

WebGL is not the same as OpenGL.

In WebGL leaving arrays enabled is explicitly allowed as long as there is a buffer attached to the attribute and (a) if it's used it's large enough to satisfy the draw call or (b) it's not used.

Unlike OpenGL ES 2.0, WebGL doesn't allow client side arrays.

Proof:

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);
canvas { border: 1px solid black; }
<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>

For webGL I'm going to go with yes, it is important to call gl.disableVertexAttribArray.

Chrome was giving me this warning:

WebGL: INVALID_OPERATION: drawElements: attribs not setup correctly

This was happening when the program changed to one using less than the maximum number of attributes. Obviously the solution was to disable the unused attributes before drawing.

If all your programs use the same number of attributes, you may well get away with calling gl.enableVertexAttribArray once on initialization. Otherwise you'll need to manage them when you change programs.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!