使用每个四边形一次绘制调用还是对所有四边形调用一次来渲染独立四边形?

Rendering independent quads using one draw call per quad or one call for all of them?

在 WebGL 应用程序中,我必须绘制一堆四边形(越多越好,但 1000 应该是一个合理的上限)。每个四边形都有一些属性,比如颜色、位置、大小,也许还有一些 material 属性。每个四边形大约有 10 个浮点数。着色器会用这些做一些奇特的事情,但这与这里无关。每个顶点可以描述为(位置+大小×(±1,±1,0))。现在我想知道如何最好地渲染所有这些四边形。我基本上看到了三个选项:

  1. 对所有参数使用制服,然后为每个四边形调用 gl.drawArrays 一次,使用数组缓冲区,其中只包含角的相对坐标,即形式的向量 (± 1,±1).这意味着由四个顶点组成的三角形带形成两个三角形。

  2. 对所有四边形一起使用单个 gl.drawArrays 调用。由于属性是每个顶点,而不是每个三角形,这意味着复制所有顶点的所有参数。此外,由于我不能用一个三角形带穿过所有顶点,我必须复制顶点,所以我基本上每个四边形有 6 个顶点,并且还不如使用不同的三角形而不是三角形带。这意味着每个四边形大约有 6×(10+2)=72 个浮点数,其中有很多冗余。

  3. 与 2. 相似,但使用 gl.drawElements 以避免重复形成每个四边形的两个三角形的顶点。所以我最终得到 4×(10+2)=48 个浮点数作为属性,6 个整数作为索引。

我不确定采用哪种方法。 None 其中感觉完全足够。在 1. 我的印象是每次调用仅绘制四个顶点的数组可能会浪费性能。我不确定使用这种方法绘制的几个四边形是否可以并行渲染。对于 2. 和 3. 我担心大量的数据冗余,以及保存数组所需的缓冲区大小。 3. 稍微减少了数据量,但可能会由于间接而涉及额外的开销。

我知道,就性能而言,最终答案是执行基准测试。但我想知道这里是否有一些既定的最佳实践,它不仅考虑了我一台开发机器上的性能,还考虑了各种硬件、驱动程序、浏览器,还考​​虑了其​​他方面,如内存的可扩展性要求。这就是我问这个问题的原因,同时我仍在努力实现适合现实生活比较的实现。

我做了一些实验,在 Linux 和 Mac 上使用 Firefox。出于某种原因,我无法获得属性帧计数器 运行,但是从对鼠标交互方法 2 的响应性来看,方法 2 明显优于 1。linux 机器上的区别更大,它有一个较旧的 nouveau-驱动显卡。因此,除非其他人发布相反的答案,否则我将以此为指导并暂时使用 2。如果我遇到内存成为问题的情况,也许会切换到 3。

减少绘图调用通常是提高性能时首先要做的事情,所以这会直接导致 1. 下降,并且随着四边形的增加只会变得更糟。

我看不出使用 2 比使用 3 有什么优势,所以我会选择 3。请记住,您始终可以使用退化三角形在不连续的对象上使用三角形带,在您的情况下是四边形。

如果您想减少冗余,而不是使用属性,请考虑使用 textures as a lookup,并对您的纹理进行编码,以便您可以简单地查找颜色。我不确定这是否会更快,但这是一种选择。