web-dev-qa-db-fra.com

Est-il important d'appeler glDisableVertexAttribArray ()?

Je ne suis pas tout à fait clair sur la portée de l'activation des tableaux d'attributs de vertex. J'ai plusieurs programmes de shader différents avec un nombre différent d'attributs de vertex. Les appels glEnableVertexAttribArray sont-ils locaux vers un programme de shaders ou globaux?

En ce moment, j'active les tableaux d'attributs vertex lorsque je crée le programme shader, et je ne les désactive jamais, et tout semble fonctionner, mais il semble que je suis probablement censé les activer/désactiver juste avant/après les appels de tirage. Y a-t-il un impact à cela?

(Je suis dans WebGL, en l'occurrence, nous parlons donc vraiment de gl.enableVertexAttribArray et gl.disableVertexAttribArray. Je noterai également que le livre orange, OpenGL Shading Language, est assez peu informatif sur ces appels.)

53
Grumdrig

L'état dans lequel les tableaux d'attributs de sommet sont activés peut être lié à un objet de tableau de sommet (VAO) ou être global.

Si vous utilisez des VAO, vous devez alors pas désactiver les tableaux d'attributs, car ils sont encapsulés dans le VAO.

Cependant, pour l'état d'activation du tableau d'attributs de vertex global, vous devez les désactiver, car s'ils restent activés, OpenGL essaiera de lire à partir des tableaux, qui peuvent être liés à un pointeur non valide, ce qui peut soit bloquer votre programme si le pointeur est à l'adresse du client espace, ou déclencher une erreur OpenGL si elle pointe hors des limites d'un objet tampon Vertex lié.

42
datenwolf

WebGL n'est pas identique à OpenGL.

Dans WebGL, laisser les tableaux activés est explicitement autorisé tant qu'un tampon est attaché à l'attribut et (a) s'il est utilisé, il est suffisamment grand pour satisfaire l'appel de dessin ou (b) qu'il n'est pas utilisé.

Contrairement à OpenGL ES 2.0, WebGL n'autorise pas les tableaux côté client.

Preuve:

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>
14
gman

Pour webGL, je vais choisir oui, il est important d'appeler gl.disableVertexAttribArray.

Chrome m'a donné cet avertissement:

WebGL: INVALID_OPERATION: drawElements: attribs not setup correctly

Cela se produisait lorsque le programme est passé à un utilisant moins que le nombre maximal d'attributs. Évidemment, la solution était de désactiver les attributs inutilisés avant de dessiner.

Si tous vos programmes utilisent le même nombre d'attributs, vous pouvez très bien ne pas appeler gl.enableVertexAttribArray une fois lors de l'initialisation. Sinon, vous devrez les gérer lorsque vous changez de programme.

4
Adria