【发布时间】:2011-06-27 06:20:26
【问题描述】:
Three.js 表示不能加载超过 65k 的顶点。 在我的纯 webgl 应用程序中,它什么也没说,但是当我尝试大对象时它不会显示整个对象。
我正在考虑拆分我的对象以放入更小的缓冲区,但这会让我感到难过。有没有更好的解决方案? 65k真的是顶点数量的极限吗?
【问题讨论】:
Three.js 表示不能加载超过 65k 的顶点。 在我的纯 webgl 应用程序中,它什么也没说,但是当我尝试大对象时它不会显示整个对象。
我正在考虑拆分我的对象以放入更小的缓冲区,但这会让我感到难过。有没有更好的解决方案? 65k真的是顶点数量的极限吗?
【问题讨论】:
据我所知,这通常受到硬件和/或驱动程序软件的限制(硬件使用 16 位索引等)。也许 Three.js 只是安全行事,并试图确保您的 webgl 应用程序适用于所有卡片。最好的方法可能是将您的模型分解成更小的块,这将确保您的应用支持当今使用的大多数 GPU。
【讨论】:
是的,WebGL 的顶点索引缓冲区目前仅限于 16 位。这是因为他们的目标是使 1.0 版本尽可能跨平台,因此有一种趋势是针对最低公分母的东西——在这种情况下,是图形硬件有限的移动平台。
一旦 1.0 发布并且最初的热潮结束,他们可能会在扩展的帮助下放松这些限制 - 应用将能够询问实现是否支持给定的扩展,并利用如果是的话 - 就像在常规桌面 OpenGL 中一样。已经有一些扩展可用,但同样它们只允许具有非常广泛的硬件支持的扩展,因此没有什么可以帮助您增加顶点数。然而,一旦他们放宽了跨平台要求,他们很可能会支持像 GL_OES_element_index_uint 这样的扩展,它允许 32 位顶点索引。
您可以阅读some discussion of these issues on the Public WebGL mailing list。
【讨论】:
目前,您可以做的是将您的大对象划分为多个 65K 元素的片段,然后重新索引每个片段,以便所有片段的索引从 0 到 65K。我已经测试过了,WebGL 允许。
现在,您将不得不锻炼在段之间共享的那些顶点。在这种情况下,最简单的替代方法是复制该顶点,这样就不再有共享顶点了。但还有更多内存友好替代方案。
我有一个关于这个工作的小演示(大脑模型大约有 350K 个顶点,分为 5 段)http://youtu.be/AXZiNHkMpZs#t=2m33s
希望对你有帮助 ;-)
【讨论】:
您可以使用drawElements(将索引数组遍历到顶点数组)或drawArrays(直接遍历顶点数组)来绘制顶点。
当您使用drawArrays 时,属性缓冲区中的顶点数似乎没有任何限制。使用drawArrays 可能不太理想,因为对于典型的网格,您必须在每次出现在图元中时指定每个顶点。另一方面,根据您的场景,这可能是一种减少 WebGL 调用次数的简单方法。
我之所以提到这一点,只是因为在阅读了这个问题及其接受的答案后,我长期以来一直认为drawArrays 中的顶点数也被限制为 65K。偶然我发现它不是,并最终通过将具有常见材质的对象聚合到单个顶点数组中来获得很大的加速(从而绕过目前似乎给 ANGLE 实现带来负担的每个缓冲区的性能开销)。
【讨论】:
drawArrays而不是drawElements!
一般其他答案都是正确的,但我想我会补充一点:
WebGL(和 OpenGL ES 2.0)唯一接受的索引数据类型是无符号字节和无符号短。由于 unsigned short 的范围为 0-65535,这意味着如果您使用 gl.DrawElements(大多数框架都这样做),则每次绘制调用只能引用 65k 个顶点。这几乎可以肯定是three.js 限制的来源。请注意,您可以在一次绘制调用中拥有超过 65k 三角形,只要它们只共享 65k 顶点。
如果您使用非索引几何 (gl.DrawArrays),每次调用可以有更多顶点,但请记住,几乎总是需要重复其中一些。我认为在大多数情况下,GPU 内存使用量的减少将证明拆分绘图调用是合理的。
【讨论】:
因为我不能对 Giles 发表评论,所以我把这个评论放在这里:
OES_element_index_uint 已添加到“社区认可的 WebGL 扩展”中!! 该扩展已在 chrome canary 中启用。 http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/
【讨论】:
自最近的 Safari 15 以来,十年过去了,WebGL2 现在已经相当普遍。WebGL2 提供了所需的信息:
gl.getParameter(GL.MAX_ELEMENT_INDEX)
gl.getParameter(GL.MAX_ELEMENTS_VERTICES)
gl.getParameter(GL.MAX_ELEMENTS_INDICES)
还有更多约束和其他数据,请参阅here[MDN]
【讨论】: