【发布时间】:2017-12-11 02:21:03
【问题描述】:
为什么 WebGL 不允许将同一个缓冲区绑定到 Array 和 Index 目标?
【问题讨论】:
标签: webgl
为什么 WebGL 不允许将同一个缓冲区绑定到 Array 和 Index 目标?
【问题讨论】:
标签: webgl
因为 WebGL 需要安全,因为它在网络浏览器中运行,所以任何随机网站或广告都可以运行 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_BUFFER 和 ELEMENT_ARRAY_BUFFER。这样做需要两种缓冲区来保存数据的副本。
注意:WebGL 实现会将与独立开发者相关的信息缓存在 ELEMENT_ARRAY_BUFFER 中。这意味着当您第一次使用给定范围的缓冲区进行绘制时,WebGL 将扫描数据的副本以确保没有索引超出范围。下次您使用相同范围使用相同的缓冲区进行绘制时,如果您没有更改缓冲区中的任何数据,那么 WebGL 已经知道最高索引并且不必再次扫描缓冲区。
【讨论】:
gl.getBufferSubData 来提取数据,然后使用gl.bufferData 或gl.bufferSubData 将该数据上传到另一个缓冲区。我很想知道为什么要在着色器中生成索引缓冲区。一些很酷的技术?