WebGL 中的 VBO 和 EBO 状态

ibe*_*ibe 1 webgl

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

设置:

bindBuffer(ARRAY_BUFFER);
bufferData(pass vertex data);
bindBuffer(ELEMENT_ARRAY_BUFFER);
bufferData(pass index data);
Run Code Online (Sandbox Code Playgroud)

画画:

bindBuffer(ELEMENT_ARRAY_BUFFER);
glDrawElements(...);
Run Code Online (Sandbox Code Playgroud)

没有bindBuffer(ARRAY_BUFFER)电话。

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

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

gma*_*man 5

如果没有 VAO,您的典型路径是这样的

设置:

create programs and lookup attribute and uniform locations
create buffers
create texture
Run Code Online (Sandbox Code Playgroud)

画画:

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
Run Code Online (Sandbox Code Playgroud)

对于 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)
Run Code Online (Sandbox Code Playgroud)

画画:

for each model
  bindVertexArray(model's VAO)
  set uniforms and bind textures 
  glDrawElements
Run Code Online (Sandbox Code Playgroud)

顺便说一句:WebGL 1 有VAO 作为扩展可在大多数设备上使用,并且有一个 polyfill,您可以使用它来让它看起来无处不在,所以如果您习惯使用 VAO,我建议您使用 polyfill。

EBO 如何知道从哪个缓冲区获取数据?

EBO 不从缓冲区获取数据,它们只是指定索引。属性从缓冲区获取数据。ARRAY_BUFFER当您调用 时,属性会记录当前绑定vertexAttribPointer。换句话说

gl.bindBuffer(ARRAY_BUFFER, bufferA);
gl.vertexAttribPointer(positionLocation, ...);
gl.bindBuffer(ARRAY_BUFFER, bufferB);
gl.vertexAttribPointer(normalLocation, ...);
gl.bindBuffer(ARRAY_BUFFER, bufferC);
gl.vertexAttribPointer(texcoordLocation, ...);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,位置将来自 bufferA,法线来自 bufferB,texcoords 来自 bufferC。无论有没有 VAO,这都是一样的。VAO 和没有 VAO 之间的区别在于属性状态(和 EBO 绑定)是全局的还是每个 VAO。