WebGL中是否存在顶点限制?

时间:2011-02-14 22:57:25

标签: web-applications webgl

Three.js表示无法加载超过65k的顶点。 在我的纯webgl应用程序中,它没有说什么,但是当我尝试大对象时它并没有显示整个对象。

我正在解决我的对象放入较小的缓冲区,但它会让我伤心。有没有更好的解决方案? 65k真的是极限量的顶点吗?

6 个答案:

答案 0 :(得分:39)

是的,WebGL的顶点索引缓冲区现在限制为16位。这是因为它们的目标是尽可能地将1.0版本作为跨平台,因此有一种趋势是将目标设定为最低的公分母 - 在这种情况下,图形硬件的移动平台就会受到影响。

一旦1.0出局并且最初的热潮已经结束,他们可能会在扩展的帮助下放松这些约束 - 应用程序将能够询问实现是否支持给定的扩展,并使用如果它 - 就像在常规桌面OpenGL中一样。已经有一些扩展可用,但是他们只允许那些具有非常广泛的硬件支持的扩展,所以没有任何东西可以帮助你增加你的顶点数。但是,一旦他们放松了跨平台需求,他们就可能支持GL_OES_element_index_uint扩展,允许32位顶点索引。

您可以阅读some discussion of these issues on the Public WebGL mailing list

答案 1 :(得分:16)

通常其他答案都是正确的,但我想我会补充一点澄清:

WebGL(和OpenGL ES 2.0)为索引接受的唯一数据类型是无符号字节和无符号短路。由于unsigned short的范围为0-65535,这意味着如果使用gl.DrawElements(大多数框架都这样做),每次绘制调用只能引用65k个顶点。这几乎肯定是three.js限制的来源。请注意,在一次绘制调用中,您可以拥有超过65k 三角形,只要它们只共享65k个顶点。

如果使用非索引几何(gl.DrawArrays),则每次调用可以有更多顶点,但请记住,几乎总是必须重复其中一些。我认为在大多数情况下,GPU内存使用量的减少将证明拆分绘制调用是合理的。

答案 2 :(得分:8)

目前,您可以做的是将每个65K元素的几个段中的大对象分开并重新索引每个段,以便所有段都具有0到65K的索引。我测试了它,WebGL允许它。

现在,您必须锻炼在段之间共享的顶点。在这种情况下,最简单的替代方法是复制该顶点,以便不再有共享顶点。但是还有更多的内存友好替代方案。

我有一个这个工作的小演示(大脑模型有大约350K顶点分为5段)http://youtu.be/AXZiNHkMpZs#t=2m33s

我希望它有所帮助; - )

答案 3 :(得分:4)

因为我无法对Giles发表评论,所以我在这里发表评论:

OES_element_index_uint已添加到“社区认可的WebGL扩展程序”中! 该扩展程序已在Chrome金丝雀中启用。 http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/

答案 4 :(得分:2)

您可以使用drawElements(遍历顶点数组遍历索引数组)或drawArrays绘制顶点,直接遍历顶点数组。

使用drawArrays时,属性缓冲区中的顶点数似乎没有任何限制。使用drawArrays可能不太理想,因为对于典型的网格,每次它在基元中出现时都必须指定每个顶点。另一方面,根据您的场景,这可能是减少WebGL调用次数的简单方法。

我之所以提到这一点,是因为在阅读了这个问题及其接受的答案之后,我很长一段时间以来认为drawArrays中的顶点数也限制在65K。偶然我发现它不是,并且最终通过将具有常见材料的对象聚合到单个顶点阵列中来获得大的加速(从而绕过目前似乎负担ANGLE实现的每缓冲器性能开销)。

答案 5 :(得分:-1)

据我所知,这通常受硬件和/或驱动程序软件的限制(硬件使用的是16位索引等)。也许Three.js只是安全地玩,并试图确保你的webgl-app适用于所有卡。可能最好的方法是将您的模型分解为更小的块,这将确保您的应用程序支持大多数(如果不是所有)当前使用的GPU。

  • 使用immediatemode(glBegin ... glEnd),你可以推动的顶点数量没有限制,但是对于那么多顶点来说它会很慢。
  • 您可以尝试将 glGetIntegerv()与GL_INDEX_BITS,GL_MAX_ELEMENTS_VERTICES和GL_MAX_ELEMENTS_INDICES一起使用,以查询卡/驱动程序支持的索引位数,最大顶点数和最大索引数。
  • 如果我没记错的话,Vertex Arrays和VBO(Vertex Buffer Object)都有相似的限制(在同一张卡/驱动程序上),因此在它们之间切换可能无济于事(不是100%肯定)