webgl中绑定缓冲区的逻辑是什么?

用户名

我有时会发现自己在以不同的顺序声明缓冲区(使用createBuffer / bindBuffer / bufferdata)与将其重新绑定到代码的其他部分(通常在绘制循环中)之间挣扎。

如果在绘制数组之前不重新绑定顶点缓冲区,则控制台会抱怨尝试访问超出范围的顶点。我的怀疑是最后一个绑定对象在指针处传递,然后传递到drawarrays,但是当我在代码开头更改顺序时,没有任何变化。有效的方法是在绘制循环中重新绑定缓冲区。因此,我无法真正理解其背后的逻辑。您何时需要重新绑定?为什么需要重新绑定?attribute0指的是什么?

man

我不知道这是否有帮助。有人说过,GL / WebGL有很多内部状态您调用的所有功能均会设置状态。完成所有设置后,您可以调用drawArrays或将drawElements所有状态用于绘制内容

SO的其他地方对此进行了解释,但是绑定缓冲区只是在WebGL内设置2个全局变量中的1个。之后,您可以通过缓冲区的绑定点来引用它。

你可以这样想

gl = function() {
   // internal WebGL state
   let lastError;
   let arrayBuffer = null;
   let vertexArray = {
     elementArrayBuffer: null,
     attributes: [
       { enabled: false, type: gl.FLOAT, size: 3, normalized: false, 
         stride: 0, offset: 0, value: [0, 0, 0, 1], buffer: null },
       { enabled: false, type: gl.FLOAT, size: 3, normalized: false, 
         stride: 0, offset: 0, value: [0, 0, 0, 1], buffer: null },
       { enabled: false, type: gl.FLOAT, size: 3, normalized: false, 
         stride: 0, offset: 0, value: [0, 0, 0, 1], buffer: null },
       { enabled: false, type: gl.FLOAT, size: 3, normalized: false, 
         stride: 0, offset: 0, value: [0, 0, 0, 1], buffer: null },
       { enabled: false, type: gl.FLOAT, size: 3, normalized: false, 
         stride: 0, offset: 0, value: [0, 0, 0, 1], buffer: null },
       ...
     ],
   }
   ...

   // Implementation of gl.bindBuffer. 
   // note this function is doing nothing but setting 2 internal variables.
   this.bindBuffer = function(bindPoint, buffer) {
     switch(bindPoint) {
       case gl.ARRAY_BUFFER;
         arrayBuffer = buffer;
         break;
       case gl.ELEMENT_ARRAY_BUFFER;
         vertexArray.elementArrayBuffer = buffer;
         break;
       default:
         lastError = gl.INVALID_ENUM;
         break;
     }
   };
...
}();

之后,其他WebGL函数将引用这些。例如gl.bufferData可能会做类似的事情

   // implementation of gl.bufferData
   // Notice you don't pass in a buffer. You pass in a bindPoint. 
   // The function gets the buffer one of its internal variable you set by
   // previously calling gl.bindBuffer

   this.bufferData = function(bindPoint, data, usage) {

     // lookup the buffer from the bindPoint
     var buffer;
     switch (bindPoint) {
       case gl.ARRAY_BUFFER;
         buffer = arrayBuffer;
         break;
       case gl.ELEMENT_ARRAY_BUFFER;
         buffer = vertexArray.elemenArrayBuffer;
         break;
       default:
         lastError = gl.INVALID_ENUM;
         break;
      }

      // copy data into buffer
      buffer.copyData(data);  // just making this up
      buffer.setUsage(usage); // just making this up
   };

与这些绑定点分开的是,有许多属性。默认情况下,属性也是全局状态。它们定义了如何从缓冲区中提取数据以提供给顶点着色器。调用将gl.getAttribLocation(someProgram, "nameOfAttribute")告诉您顶点着色器将查看哪个属性以从缓冲区中获取数据。

因此,有4个函数可用于配置属性如何从缓冲区中获取数据。gl.enableVertexAttribArraygl.disableVertexAttribArraygl.vertexAttribPointer,和gl.vertexAttrib??

他们有效地实施了这样的事情

this.enableVertexAttribArray = function(location) {
  const attribute = vertexArray.attributes[location];
  attribute.enabled = true;  // true means get data from attribute.buffer 
};

this.disableVertexAttribArray = function(location) {
  const attribute = vertexArray.attributes[location];
  attribute.enabled = false; // false means get data from attribute.value
};

this.vertexAttribPointer = function(location, size, type, normalized, stride, offset) {
  const attribute = vertexArray.attributes[location];
  attribute.size       = size;       // num values to pull from buffer per vertex shader iteration
  attribute.type       = type;       // type of values to pull from buffer
  attribute.normalized = normalized; // whether or not to normalize
  attribute.stride     = stride;     // number of bytes to advance for each iteration of the vertex shader. 0 = compute from type, size
  attribute.offset     = offset;     // where to start in buffer.

  // IMPORTANT!!! Associates whatever buffer is currently *bound* to 
  // "arrayBuffer" to this attribute
  attribute.buffer     = arrayBuffer;
};

this.vertexAttrib4f = function(location, x, y, z, w) {
  const attribute = vertexArray.attributes[location];
  attribute.value[0] = x;
  attribute.value[1] = y;
  attribute.value[2] = z;
  attribute.value[3] = w;
};

现在,当您调用gl.drawArraysgl.drawElements系统知道要如何从为提供顶点着色器而制作的缓冲区中提取数据时。看到这里如何工作

由于属性是全局状态,这意味着每次调用drawElementsdrawArrays设置属性的方式都是如何使用它们。如果将属性#1和#2设置为每个缓冲区具有3个顶点,但要求绘制6个顶点,gl.drawArrays则会出现错误。类似地,如果您创建绑定到绑定点的索引缓冲区,gl.ELEMENT_ARRAY_BUFFER并且该缓冲区的索引大于2,则会得到该index out of range错误。如果你的缓冲区只有3个顶点,那么唯一的有效的指标是012

通常,每次绘制不同的东西时,都会重新绑定绘制该东西所需的所有属性。绘制具有位置和法线的立方体?将缓冲区与位置数据绑定,设置用于位置的属性,将缓冲区与法线数据绑定,设置用于法线的属性,现在绘制。接下来,绘制一个包含位置,顶点颜色和纹理坐标的球体。绑定包含位置数据的缓冲区,设置用于位置的属性。绑定包含顶点颜色数据的缓冲区,设置用于顶点颜色的属性。绑定包含纹理坐标的缓冲区,设置用于纹理坐标的属性。

唯一不重新绑定缓冲区的情况是,如果您绘制同一件事不止一次。例如画10个立方体。您将重新绑定缓冲区,然后为一个立方体设置制服,绘制它,为下一个立方体设置制服,绘制它,重复。

我还应该补充说,有一个扩展名[ OES_vertex_array_object],它也是WebGL 2.0的功能。顶点数组对象是上面称为的全局状态,vertexArray其中包括elementArrayBuffer和所有属性。

调用gl.createVertexArray使其中之一成为新的。调用gl.bindVertexArray将全局设置attributes为指向绑定的vertexArray中的一个。

gl.bindVertexArray然后打电话

 this.bindVertexArray = function(vao) {
   vertexArray = vao ? vao : defaultVertexArray;
 }    

这样做的好处是,您可以在初始化时设置所有属性和缓冲区,然后在绘制时只需1个WebGL调用即可设置所有缓冲区和属性。

这是一个webgl状态图,可能有助于更好地可视化。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Pytorch中的缓冲区是什么?

来自分类Dev

解除绑定OpenGL缓冲区的作用是什么?

来自分类Dev

WebGL中的模板缓冲区

来自分类Dev

nio缓冲区类中limit()的用途是什么

来自分类Dev

解除绑定WebGL缓冲区,值得吗?

来自分类Dev

在openGL中多次绑定缓冲区

来自分类Dev

在设置绑定接口之前,系统本地管理NIC环形缓冲区大小的方法是什么?

来自分类Dev

WebGL 渲染缓冲区

来自分类Dev

为什么WebGL“清除”吸引前端缓冲区?

来自分类Dev

WebGL。是否在GPU中创建缓冲区?

来自分类Dev

更新WebGL 2中的统一缓冲区数据?

来自分类Dev

更新WebGL 2中的统一缓冲区数据?

来自分类Dev

在Rust中实现字符串缓冲区的最佳方法是什么?

来自分类Dev

协议缓冲区第2版中的“ import弱”是什么意思?

来自分类Dev

协议缓冲区和Avro中的ZigZag编码背后的原因是什么?

来自分类Dev

ARKit深度图像素缓冲区中的黑色像素是什么?

来自分类Dev

在Vulkan中重新提交待处理命令缓冲区的用例是什么

来自分类Dev

I / O缓冲区错误中此[4200.237911]的状态是什么?

来自分类Dev

vim中的缓冲区或制表符?每种方法的优点/缺点是什么?

来自分类Dev

协议缓冲区第2版中的“ import弱”是什么意思?

来自分类Dev

交换链中 DXGI_USAGE_UNORDERED_ACCESS 缓冲区使用的意义是什么?

来自分类Dev

标准C库中缓冲区大小的特殊宏是什么?

来自分类Dev

处理结构的OpenCL缓冲区的正确方法是什么?

来自分类Dev

OpenGL纹理缓冲区对象的目的是什么?

来自分类Dev

是什么使glBufferSubData在大缓冲区上变慢?

来自分类Dev

30%的RAM是“缓冲区”。它是什么?

来自分类Dev

“写入缓存缓冲区刷新”是什么意思

来自分类Dev

OpenGL纹理缓冲区对象的目的是什么?

来自分类Dev

如何绑定q关闭Vim中的只读缓冲区?

Related 相关文章

  1. 1

    Pytorch中的缓冲区是什么?

  2. 2

    解除绑定OpenGL缓冲区的作用是什么?

  3. 3

    WebGL中的模板缓冲区

  4. 4

    nio缓冲区类中limit()的用途是什么

  5. 5

    解除绑定WebGL缓冲区,值得吗?

  6. 6

    在openGL中多次绑定缓冲区

  7. 7

    在设置绑定接口之前,系统本地管理NIC环形缓冲区大小的方法是什么?

  8. 8

    WebGL 渲染缓冲区

  9. 9

    为什么WebGL“清除”吸引前端缓冲区?

  10. 10

    WebGL。是否在GPU中创建缓冲区?

  11. 11

    更新WebGL 2中的统一缓冲区数据?

  12. 12

    更新WebGL 2中的统一缓冲区数据?

  13. 13

    在Rust中实现字符串缓冲区的最佳方法是什么?

  14. 14

    协议缓冲区第2版中的“ import弱”是什么意思?

  15. 15

    协议缓冲区和Avro中的ZigZag编码背后的原因是什么?

  16. 16

    ARKit深度图像素缓冲区中的黑色像素是什么?

  17. 17

    在Vulkan中重新提交待处理命令缓冲区的用例是什么

  18. 18

    I / O缓冲区错误中此[4200.237911]的状态是什么?

  19. 19

    vim中的缓冲区或制表符?每种方法的优点/缺点是什么?

  20. 20

    协议缓冲区第2版中的“ import弱”是什么意思?

  21. 21

    交换链中 DXGI_USAGE_UNORDERED_ACCESS 缓冲区使用的意义是什么?

  22. 22

    标准C库中缓冲区大小的特殊宏是什么?

  23. 23

    处理结构的OpenCL缓冲区的正确方法是什么?

  24. 24

    OpenGL纹理缓冲区对象的目的是什么?

  25. 25

    是什么使glBufferSubData在大缓冲区上变慢?

  26. 26

    30%的RAM是“缓冲区”。它是什么?

  27. 27

    “写入缓存缓冲区刷新”是什么意思

  28. 28

    OpenGL纹理缓冲区对象的目的是什么?

  29. 29

    如何绑定q关闭Vim中的只读缓冲区?

热门标签

归档