为什么 gl.drawElements 需要重新绑定而 gl.drawArrays 不需要?
Why is that gl.drawElements needs rebind while gl.drawArrays doesn't?
大家好,最近在学习webgl
有两个片段可以完成同一件事 - 画一个正方形。一种是对 6 个顶点使用 gl.drawArrays,一种是对 4 个顶点使用 gl.drawElements。
不过我注意到,在使用gl.drawArrays的时候,我们可以先解绑gl.ARRAY_BUFFER再使用,没关系。查看片段。
function initBuffers() {
/*
V0 V3
(-0.5, 0.5, 0) (0.5, 0.5, 0)
X---------------------X
| |
| |
| (0, 0) |
| |
| |
X---------------------X
V1 V2
(-0.5, -0.5, 0) (0.5, -0.5, 0)
*/
const vertices = [
// first triangle (V0, V1, V2)
-0.5, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
// second triangle (V0, V2, V3)
-0.5, 0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0
];
// Setting up the VBO
squareVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(program.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(program.aVertexPosition);
// Clean
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
function draw() {
// Clear the scene
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 6);
// Clean
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
initBuffers()
在 draw()
之前调用。请注意,我在调用 gl.drawArrays
之前已经取消绑定 gl.ARRAY_BUFFER
并且它成功绘制了正方形。
然而,当使用 gl.drawElements 时,我必须确保 gl.ELEMENT_ARRAY_BUFFER
当前绑定到正确的索引。例如
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
如果我像 gl.drawArrays
一样使用 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
,我必须在调用 gl.drawElements
.
之前使用 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
重新绑定它
这主要在这个答案中解释:
简短版本 gl.drawArrays
仅使用属性。当您调用 gl.vertexAttribPointer
时,属性具有绑定到它们的缓冲区。在您调用 gl.verexAttribPointer
时绑定的缓冲区 do gl.ARRAY_BUFFER
将被复制到该属性的状态中。
属性本身是当前顶点数组对象 (VAO) 的状态,就像当前 ELEMENT_ARRAY_BUFFER 一样。 VAO 是 WebGL1 中的可选扩展,也是 WebGL2 的标准部分。
再次参考这个答案: 以及这个答案:
大家好,最近在学习webgl
有两个片段可以完成同一件事 - 画一个正方形。一种是对 6 个顶点使用 gl.drawArrays,一种是对 4 个顶点使用 gl.drawElements。
不过我注意到,在使用gl.drawArrays的时候,我们可以先解绑gl.ARRAY_BUFFER再使用,没关系。查看片段。
function initBuffers() {
/*
V0 V3
(-0.5, 0.5, 0) (0.5, 0.5, 0)
X---------------------X
| |
| |
| (0, 0) |
| |
| |
X---------------------X
V1 V2
(-0.5, -0.5, 0) (0.5, -0.5, 0)
*/
const vertices = [
// first triangle (V0, V1, V2)
-0.5, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
// second triangle (V0, V2, V3)
-0.5, 0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0
];
// Setting up the VBO
squareVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(program.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(program.aVertexPosition);
// Clean
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
function draw() {
// Clear the scene
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 6);
// Clean
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
initBuffers()
在 draw()
之前调用。请注意,我在调用 gl.drawArrays
之前已经取消绑定 gl.ARRAY_BUFFER
并且它成功绘制了正方形。
然而,当使用 gl.drawElements 时,我必须确保 gl.ELEMENT_ARRAY_BUFFER
当前绑定到正确的索引。例如
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
如果我像 gl.drawArrays
一样使用 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
,我必须在调用 gl.drawElements
.
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
重新绑定它
这主要在这个答案中解释:
简短版本 gl.drawArrays
仅使用属性。当您调用 gl.vertexAttribPointer
时,属性具有绑定到它们的缓冲区。在您调用 gl.verexAttribPointer
时绑定的缓冲区 do gl.ARRAY_BUFFER
将被复制到该属性的状态中。
属性本身是当前顶点数组对象 (VAO) 的状态,就像当前 ELEMENT_ARRAY_BUFFER 一样。 VAO 是 WebGL1 中的可选扩展,也是 WebGL2 的标准部分。
再次参考这个答案: 以及这个答案: