如果没有 VAO,您的典型路径是这样的
设置:
create programs and lookup attribute and uniform locations
create buffers
create texture
绘图:
for each model
for each attribute
bindBuffer(ARRAY_BUFFER, model's buffer for attribute)
vertexAttribPointer(...)
bindBuffer(ELEMENT_ARRAY_BUFFER, model's ebo)
set uniforms and bind textures
glDrawElements
对于 VAO,这会变为
设置:
create programs and lookup attribute and uniform locations
create buffers
create texture
for each model
create and bind VAO
for each attribute
bindBuffer(ARRAY_BUFFER, model's buffer for attribute)
vertexAttribPointer(...)
bindBuffer(ELEMENT_ARRAY_BUFFER, model's ebo)
绘图:
for each model
bindVertexArray(model's VAO)
set uniforms and bind textures
glDrawElements
顺便说一句:WebGL 1 有 VAOs as an extension 和 is available on most devices 和 a polyfill,你可以使用它来让它看起来无处不在,所以如果你习惯使用 VAO,我建议使用 polyfill。
EBO 如何知道从哪个缓冲区获取数据?
EBO 不从缓冲区中获取数据,它们只是指定索引。属性从缓冲区获取数据。当您调用vertexAttribPointer 时,属性会记录当前的ARRAY_BUFFER 绑定。换句话说
gl.bindBuffer(ARRAY_BUFFER, bufferA);
gl.vertexAttribPointer(positionLocation, ...);
gl.bindBuffer(ARRAY_BUFFER, bufferB);
gl.vertexAttribPointer(normalLocation, ...);
gl.bindBuffer(ARRAY_BUFFER, bufferC);
gl.vertexAttribPointer(texcoordLocation, ...);
在这种情况下,位置将来自缓冲区A,法线来自缓冲区B,texcoords 来自缓冲区C。无论有没有 VAO,这都是一样的。 VAO 和无 VAO 的区别在于属性状态(和 EBO 绑定)是全局的还是每个 VAO。