33

Three.js 说它不能加载超过 65k 的顶点。

在我的纯 webgl 应用程序中,它什么也没说,但是当我尝试大对象时它不会显示整个对象。

我可以将我的对象分割成更小的缓冲区,但这会让我感到难过。

有没有更好的解决方案?65k 真的是顶点的限制数量吗?

4

7 回答 7

42

是的,WebGL 的顶点索引缓冲区目前仅限于 16 位。这是因为他们的目标是让 1.0 版尽可能跨平台,所以有一种趋势是让东西以最小的公分母为目标——在这种情况下,移动平台的图形硬件有限。

一旦 1.0 发布并且最初的热潮结束,他们可能会在扩展的帮助下放松这些限制——应用程序将能够询问实现是否支持给定的扩展,如果支持就使用它是——就像在普通的桌面 OpenGL 中一样。已经有一些扩展可用,但同样它们只允许具有非常广泛的硬件支持的扩展,因此没有什么可以帮助您增加顶点数。然而,一旦他们放宽了跨平台的要求,他们很可能会支持像 GL_OES_element_index_uint 扩展这样允许 32 位顶点索引的东西。

您可以在 Public WebGL 邮件列表中阅读有关这些问题的一些讨论

于 2011-02-16T14:59:30.770 回答
19

通常其他答案是正确的,但我想我会添加一些说明:

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

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

于 2011-10-04T01:24:57.063 回答
10

目前,你可以做的是将你的大对象分成几个段,每个段有 65K 个元素,并重新索引每个段,这样所有段的索引都在 0 到 65K 之间。我已经对其进行了测试,并且 WebGL 允许它。

现在,您将不得不锻炼在段之间共享的那些顶点。在这种情况下,最简单的替代方法是复制该顶点,这样就不再有共享顶点了。但是还有更多对内存友好的选择。

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

我希望它有帮助;-)

于 2011-03-04T04:02:02.163 回答
6

因为我不能对 Giles 发表评论,所以我把这个评论放在这里:

OES_element_index_uint 已添加到“社区批准的 WebGL 扩展”中!!该扩展已在 chrome canary 中启用。 http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/

于 2012-11-07T02:09:14.503 回答
5

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

当您使用drawArrays. 使用drawArrays可能不太理想,因为对于典型的网格,您必须在每次出现在图元中时指定每个顶点。另一方面,根据您的场景,这可能是一种减少 WebGL 调用次数的简单方法。

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

于 2011-04-30T18:43:19.223 回答
1

自最近的 Safari 15 以来,十年过去了,WebGL2 现在非常普遍。WebGL2 提供了所需的信息:

gl.getParameter(GL.MAX_ELEMENT_INDEX)
gl.getParameter(GL.MAX_ELEMENTS_VERTICES)
gl.getParameter(GL.MAX_ELEMENTS_INDICES)

还有更多约束和其他数据,请参见此处[MDN]

于 2021-12-29T02:06:59.637 回答
-1

As far as I know, this is usually limited by the hardware and/or driver software (hardware is using 16-bit indices or such). Maybe Three.js just plays it safe and tries to makes sure your webgl-app works on all cards. Probably the best way is to break your models down into smaller chunks, this will make sure your app supports most if not all GPUs in use today.

  • Using immediatemode (glBegin...glEnd), there is no restriction in the amount of vertices you can push through, but it's going to be slow with that many vertices.
  • You could try using glGetIntegerv() with GL_INDEX_BITS, GL_MAX_ELEMENTS_VERTICES and GL_MAX_ELEMENTS_INDICES to query the amount of index bits, maximum vertices and maximum indices the card/driver supports.
  • If I remember correctly, Vertex Arrays and VBOs (Vertex Buffer Object) both have similar limits (on the same card/driver), so switching between them probably won't help (not 100% sure on this)
于 2011-02-15T06:04:23.603 回答