WebGL 中的 VBO 和 EBO 状态

VBO and EBO state in WebGL

在 WebGL 中使用索引缓冲区绘制一些东西,你会稍微经历这个例程(如 MDN 所暗示的):

设置:

bindBuffer(ARRAY_BUFFER);
bufferData(pass vertex data);
bindBuffer(ELEMENT_ARRAY_BUFFER);
bufferData(pass index data);

绘图:

bindBuffer(ELEMENT_ARRAY_BUFFER);
glDrawElements(...);

没有 bindBuffer(ARRAY_BUFFER) 来电。

假设我有多个带有顶点数据的 VBO。 EBO 如何知道从哪个缓冲区获取数据?

在标准 OpenGL 中,我会将其封装在 VAO 中。但是让我感到困惑的是 WebGL 中缺少它。

如果没有 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 which is available on most devices and there's a polyfill,您可以使用它来让它看起来无处不在,所以如果您习惯使用 VAO,我建议您使用 polyfill。

How does an EBO will know from which buffer to take the data?

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,纹理坐标来自缓冲区 C。有或没有 VAO 都是一样的。 VAO 和无 VAO 之间的区别在于属性状态(和 EBO 绑定)是全局的还是每个 VAO。