Подтвердить что ты не робот

Важно ли вызывать glDisableVertexAttribArray()?

Я не совсем понимаю сферу применения массивов атрибутов вершин. У меня есть несколько разных шейдерных программ с различным количеством атрибутов вершин. Являются ли glEnableVertexAttribArray вызовы локальными для шейдерной программы или глобальными?

В настоящее время я разрешаю массивы атрибутов вершины при создании шейдерной программы и никогда не отключаю их, и все, похоже, работает, но похоже, что я, возможно, должен включать/отключать их прямо до/после вызовов рисования, Есть ли влияние на это?

(Я в WebGL, так как это происходит, поэтому мы действительно говорим о gl.enableVertexAttribArray и gl.disableVertexAttribArray. Я также хочу отметить, что оранжевая книга OpenGL Shading Language довольно неинформативна в отношении этих вызовов. )

4b9b3361

Ответ 1

Состояние, в котором разрешены массивы атрибутов Vertex, может быть привязано к объекту вершинного массива (VAO) или глобальным.

Если вы используете VAO, вам не следует отключать массивы атрибутов, поскольку они инкапсулированы в VAO.

Однако для глобального разрешенного массива атрибутов атрибутов вы должны отключить их, потому что если они оставлены включенными, OpenGL попытается прочитать из массивов, которые могут быть связаны с недопустимым указателем, что может привести к сбою вашей программы, если указатель на адресное пространство клиента или поднять ошибку OpenGL, если она указывает пределы допустимого объекта буфера Vertex.

Ответ 2

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);
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>

Ответ 3

Для webGL я собираюсь использовать да, важно вызвать gl.disableVertexAttribArray.

Chrome дал мне это предупреждение:

WebGL: INVALID_OPERATION: drawElements: attribs not setup correctly

Это происходило, когда программа изменилась на один, используя меньшее, чем максимальное количество атрибутов. Очевидно, что решение заключалось в том, чтобы отключить неиспользуемые атрибуты перед рисованием.

Если все ваши программы используют одинаковое количество атрибутов, вы можете уйти с вызовом gl.enableVertexAttribArray один раз при инициализации. В противном случае вам придется управлять ими при изменении программ.