Важно ли вызывать glDisableVertexAttribArray()?
Я не совсем понимаю сферу применения массивов атрибутов вершин. У меня есть несколько разных шейдерных программ с различным количеством атрибутов вершин. Являются ли glEnableVertexAttribArray
вызовы локальными для шейдерной программы или глобальными?
В настоящее время я разрешаю массивы атрибутов вершины при создании шейдерной программы и никогда не отключаю их, и все, похоже, работает, но похоже, что я, возможно, должен включать/отключать их прямо до/после вызовов рисования, Есть ли влияние на это?
(Я в WebGL, так как это происходит, поэтому мы действительно говорим о gl.enableVertexAttribArray
и gl.disableVertexAttribArray
. Я также хочу отметить, что оранжевая книга OpenGL Shading Language довольно неинформативна в отношении этих вызовов. )
Ответы
Ответ 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 один раз при инициализации. В противном случае вам придется управлять ими при изменении программ.