【问题标题】:BindBuffer and BufferData called back to backBindBuffer 和 BufferData 背靠背调用
【发布时间】:2020-02-24 01:26:22
【问题描述】:

在 OpenGL ES(或者在我的情况下,WebGL)中,我看不到将顶点和颜色缓冲区背靠背绑定然后调用 drawArrays 是如何工作的。例如,这里有一些示例代码供您理解:

vertexBuffer = glCreateBuffer();
glBindBuffer(GL_ARRAY_BUFFER, vertextBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);

colorBuffer = glCreateBuffer();
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, colors, GL_STATIC_DRAW);

glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);

如果我首先将 GL_ARRAY_BUFFER 绑定到顶点 bufferData,然后再绑定一些颜色,那么幕后发生了什么?在我看来,应该忽略顶点信息,因为我在它之后将颜色信息绑定到 GL_ARRAY_BUFFER。

【问题讨论】:

  • 实际上,如果这是您的全部代码,那么它不起作用,因为您没有设置任何顶点数组指针。
  • 是的,关于 opengl 我缺少的一点是顶点属性的分配,@derhass 解释了这一点。对不起这个不好的例子(现在我知道我误解了什么)。

标签: graphics opengl-es webgl


【解决方案1】:

gl.vertexAttribPointer 是实际设置哪些属性使用哪些缓冲区。

你可以把它想象成

gl = { 
   arrayBuffer: someBuffer, 
   vertexArray: {
     elementArrayBuffer: someOtherBuffer,
     attributes: [], 
   },
};

当您调用 gl.bindBuffer 时,您只是将 2 个全局变量之一设置为 gl 状态。

gl.bindBuffer = function(bindPoint, buffer) {
   switch (bindPoint) {
      case: this.ARRAY_BUFFER:
         this.arrayBuffer = buffer;
         break;
      case: this.ELEMENT_ARRAY_BUFFER:
         this.vertexArray.elementArrayBuffer = buffer;
         break;
   }
};

当您调用gl.vertexAttribPointer 时,它会将arrayBuffer 的当前值复制到指定的属性。

gl.vertexAttribPointer = function(index, size, type, normalized, stride, offset) {
    var attribute = this.vertexArray.attributes[index];
    attribute.size = size;
    attribute.type = type;
    attribute.normalized = normalized;
    attribute.stride = stride;
    attribute.offset = offset;
    attribute.buffer = this.arrayBuffer;  // copies the current buffer reference.
};

除了只有 1 个全局变量之外,纹理的工作方式类似

gl = { 
    activeTextureUnit: 0,
    textureUnits: [], 
};

gl.activeTexture 设置您正在处理的纹理单元。

gl.activeTexture = function(unit) {
   this.activeTextureUnit = unit - this.TEXTURE_0;  // make it zero based.
};

每个纹理单元都有一个TEXTURE_2D 和一个TEXTURE_CUBEMAP 所以gl.bindTexture(b, t) 是有效的

gl.bindTexture = function(bindPoint, texture) {
   var textureUnit = this.textureUnits[this.activeTextureUnit];
   switch (bindPoint) {
       case this.TEXTURE_2D:
           textureUnit.texture2D = texture;
           break;
       case this.TEXTURE_CUBEMAP:
           textureUnit.textureCubeMap = texture;
           break;
   }
};

这是webgl state diagram

【讨论】:

  • 这是我根据之前的答案在脑海中想象出来的,但非常感谢你写出来!
  • @gman 那么这是否意味着如果发布者想要设置颜色和顶点属性(我认为他想要这样做),他将不得不调用 gl.vertexAttribPointer 并调用 @ 987654338@ 在对gl.bindBuffer 的调用之间?
  • 简短的回答是webglfundamentals.org/webgl/lessons/…
  • 我认为这是一个了不起的答案。
【解决方案2】:

glDrawArrays() 根本不关心 GL_ARRAY_BUFFER 绑定了什么。它确实关心顶点属性指针。

这里真正重要的不是您粘贴的代码:属性指针设置。当调用glVertexAttribPointer() 时,对当前绑定的GL_ARRAY_BUFFER 的引用将成为属性指针的一部分。不同的属性可以来自不同的 VBO,或者您可以使用一个 VBO 作为多个属性的来源,这完全取决于您。

【讨论】:

  • 啊好吧,我想我现在明白了。它就像 GL_ARRAY_BUFFER 只是一个全局变量,用于 glVertextAttribPointer 的实现。如果我要执行我在示例中所做的操作,但不调用 glVertexAttribPointer,那么它将无法工作,因为 GL_ARRAY_BUFFER 在通过 glVertexAttribPointer 分配给着色器属性之前会被覆盖。
  • 好吧。 GL_ARRAY_BUFFER 绑定是 GL state 的一部分,实际上是一个全局绑定(关于 GL 上下文)。是的,在设置顶点属性指针时,这种状态是相关的。它也与其他一些事情相关,尤其是在使用GL_ARRAY_BUFFER 目标时任何带有缓冲区的 GL 函数操作。
猜你喜欢
  • 2022-11-03
  • 2015-09-08
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多