绘制多个对象时,什么时候创建新的顶点数组对象?

When drawing multiple objects, when do you create a new vertex array object?

我正在尝试使用 WebGL 创建游戏。

我目前有三个纹理,一个是字体的字母,一个是角色的精灵 sheet,一个是世界的 tilemap。所以我有几个大的纹理,我需要多次绘制其中的一小部分。

最好的方法是什么?

我目前的方法是为每个字母、地图上的正方形、角色姿势等使用一个 VAO...所以我会有 150 多个 VAO。我认为 VAO 很好,因为它们既简单又快速,但 this, this 和其他人认为这似乎不是最佳选择。

我知道的另一种方法是只有三个 VAO,并更改 WebGL 在缓冲区中开始读取的位置,例如,以获得正确字母的位置。因此,我不会使用数百个带有微型阵列的 VAO,而是使用三个带有大型阵列的 VAO。如果这是正确的方法,我是否必须在每次绘制内容时在 gl.enablevertexAttribArray() 之后调用 gl.vertexAttribPointer(),还是只修改 gl.drawArrays() 中的计数参数?

gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ) 是 16 或 32,所以切碎纹理似乎也不是一个好方法。

最好的概念方法是什么?

多少个 VAO 由您决定。有很多权衡。就文本而言,最常见的文本方式是将字形放入纹理图集中,并生成一个缓冲区,其中包含要绘制的所有字母的顶点。

也就是说。

each frame
   for each string
      for each letter in string
         add vertices for letter to buffer

drawArray/drawElements(gl.TRIANGLES, ... totalOfAllLettersInAllStrings * 6);

因此,所有字母可能只有一个绘制调用(例如 UI)。每个字母没有一个。那将是减慢速度的方式。

Here's an article on it

您对 MAX_TEXTURE_IMAGE_UNITS 的评论听起来好像还有一个 mis-understanding?纹理单元只是着色器在单个绘制调用中可以引用的最大纹理数。它们不是最大数量的纹理周期。您可以拥有 1000 种纹理。您只能在每次绘制调用中为它们引用特定的数字。

就绘制文本而言,对于简单的情况,通常每种字体样式只需要一个纹理。 虽然如果你想支持所有的 unicode 而不是只支持 ASCII,它会很快变得复杂。