为什么WebGL不允许将相同的缓冲区绑定到Array_Buffer和Element_Array_Buffer?

时间:2017-07-06 22:14:00

标签: webgl

参考:https://github.com/tmpvar/WebGL-standalone/blob/master/test/khronos-tests/conformance/buffers/buffer-bind-test.html

为什么WebGL不允许将相同的缓冲区绑定到Array和Index目标?

1 个答案:

答案 0 :(得分:1)

由于WebGL在Web浏览器中运行需要安全,因此任何随机网站或广告都可以运行WebGL代码。

为了确保安全,必须检查所有用法是否读取或写入任何超出范围的数据。一个简单的输入示例是调用宽度和高度较大但缓冲区太小的gl.texImage2D。普通C OpenGL将很乐意读取缓冲区的末尾,但WebGL不会,并且会出错。一个简单的输出示例是调用gl.readPixels,并为给定的宽度和高度调整缓冲区。 OpenGL很乐意将内存丢弃到缓冲区之外。 WebGL将生成错误。

因此,类似地,当您调用gl.drawElements时,您使用索引缓冲区来访问其他缓冲区中的数据。如果这些索引中的任何一个太大,他们将访问越界数据。例如,你有一个属性的缓冲区有3个顶点,但你的索引是3.唯一的范围索引是0,1和2.OpenGL并不关心这个,但WebGL确实如此。

因此,为了确保您无法做到,WebGL必须验证您的索引。换句话说,它必须通读您的ELEMENT_ARRAY_BUFFER并检查没有索引会引用超出范围的数据。要做到这一点,它必须保留ELEMENT_ARRAY_BUFFER中的数据副本(因为OpenGL ES 2.0无法从缓冲区读取数据,即使这样做也会太慢)。 WebGL的缓冲区中的数据副本使用内存,因此为了不浪费内存,只有ELEMENT_ARRAY_BUFFER生成的缓冲区保留了其数据的副本。其他缓冲区不需要拥有其数据的副本。

由于这两种类型的缓冲区在WebGL中不兼容,因此您无法将ARRAY_BUFFERELEMENT_ARRAY_BUFFER绑定到一个。要做到这一点,需要两种缓冲区来保存数据的副本。

注意:WebGL实现在ELEMENT_ARRAY_BUFFER中缓存与indies相关的信息。这意味着第一次使用缓冲区绘制给定范围时,WebGL将扫描数据副本以确保没有索引超出范围。下次使用相同的范围绘制相同的缓冲区时,如果您还没有更改缓冲区中的任何数据,那么WebGL已经知道最高的索引,并且不必再次扫描缓冲区。