嗨,我正在学习webgl。
我一直在读一本书Real-Time 3D Graphics with WebGL 2
,这里说的是顶点数组对象,使我们可以将一组缓冲区的所有顶点/索引绑定信息存储在单个易于管理的对象中。
它为VAO提供了此示例。
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 = [
-0.5, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0
];
// Indices defined in counter-clockwise order
indices = [0, 1, 2, 0, 2, 3];
// Create VAO instance
squareVAO = gl.createVertexArray();
// Bind it so we can work on it
gl.bindVertexArray(squareVAO);
const squareVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// Provide instructions for VAO to use data later in draw
gl.enableVertexAttribArray(program.aVertexPosition);
gl.vertexAttribPointer(program.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
// Setting up the IBO
squareIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
// Clean
gl.bindVertexArray(null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
// We call draw to render to our canvas
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);
// Bind the VAO
gl.bindVertexArray(squareVAO);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
// Draw to the scene using triangle primitives
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
// Clean
gl.bindVertexArray(null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
// Entry point to our application
function init() {
// Retrieve the canvas
const canvas = utils.getCanvas('webgl-canvas');
// Set the canvas to the size of the screen
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Retrieve a WebGL context
gl = utils.getGLContext(canvas);
// Set the clear color to be black
gl.clearColor(0, 0, 0, 1);
// Call the functions in an appropriate order
initProgram();
initBuffers();
draw();
}
这里的问题是,在将VAO绑定到gl.bindBuffer();
后,是否需要draw()
?
我查看了此链接What are Vertex Arrays in OpenGL & WebGL2?,它说
At draw time it then only takes one call to gl.bindVertexArray to setup all the attributes and the ELEMENT_ARRAY_BUFFER
。因此,我认为在将gl.bindBuffer();
绑定VAO之后是否不需要draw()
?
教科书中的代码会误导人吗?
答案 0 :(得分:0)
否,您不需要重新绑定缓冲区
ELEMENT_ARRAY_BUFFER绑定是您链接到的答案所指出的当前顶点阵列状态的一部分。
您的示例中的这些行也不相关
在initBuffers
// Clean
gl.bindVertexArray(null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
这些行都不是真正需要的。即使不需要,只有第一行具有任何实际点
此行
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
并没有真正做任何事情,因为如上所述ELEMENT_ARRAY_BUFFER
状态是当前顶点数组的一部分,因此仅更改gl.bindVertexArray
的当前顶点数组就已经改变了绑定。
此行
gl.bindBuffer(gl.ELEMENT_BUFFER, null);
毫无意义,因为AFAIK几乎没有程序会仅假设当前的ARRAY_BUFFER绑定设置为任何值。他们总是在操作缓冲区之前先绑定一个缓冲区。拥有它还不错,我敢肯定,您可以找到一些令人费解的方法使其变得重要,但在现实生活中,我还没有见过。
这行有一点。
gl.bindVertexArray(null);
通常将顶点缓冲区与顶点属性分开设置。如果您要绘制的每个物体都制作一个顶点阵列,而您的图案就是这样
// at init time
for each thing I plan to draw
(1) create buffers and fill with positions/normals/texcoords/indices
(2) create/bind vertex array
(3) setup attributes and ELEMENT_ARRAY_BUFFER
然后,如果您在第3步之后未绑定null
,则第1步将最终更改先前绑定的顶点数组的ELEMENT_ARRAY_BUFFER绑定
换句话说,这行
gl.bindVertexArray(null);
有一点。不过,这是有争议的。如果您交换了步骤1和2,并将初始化更改为
// at init time
for each thing I plan to draw
(1) create/bind vertex array
(2) create buffers and fill with positions/normals/texcoords/indices
(3) setup attributes
然后问题就解决了
draw
中存在相同的3行
// Clean
gl.bindVertexArray(null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
他们又没有意义的地方