【问题标题】:Why doesn't WebGL allow binding the same buffer to Array_Buffer and Element_Array_Buffer?为什么 WebGL 不允许将同一个缓冲区绑定到 Array_Buffer 和 Element_Array_Buffer?
【发布时间】:2017-12-11 02:21:03
【问题描述】:

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

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

【问题讨论】:

    标签: webgl


    【解决方案1】:

    因为 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_BUFFERELEMENT_ARRAY_BUFFER。这样做需要两种缓冲区来保存数据的副本。

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

    【讨论】:

    • 那么到底有没有使用变换反馈生成元素数组缓冲区?
    • 不是直接的。您必须调用gl.getBufferSubData 来提取数据,然后使用gl.bufferDatagl.bufferSubData 将该数据上传到另一个缓冲区。我很想知道为什么要在着色器中生成索引缓冲区。一些很酷的技术?
    • 不,只是我需要生成一些非常大的地形网格,所以在GPU上做会更快。我想我可以在 webworker 中生成索引数组。我正在探索使用更多实例与使用更大图块之间的替代方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    相关资源
    最近更新 更多