WebGL/OpenGL 性能,使用一半的顶点缓冲区



我有一个应用程序,您可以在其中放大/缩小,您应该会看到一些细节丰富的模型或许多细节较低的模型。所以我想使用一些LOD技术。

我想知道如果我只使用一个带有仓位的缓冲区(一个带有法线的缓冲区,...),但每个 LOD 都有不同的索引,性能会如何?

更准确地说,假设我想实现 5 个 LOD 级别。具有高细节 (LOD1) 的模型具有 ~5k 顶点,全部用于渲染 ~5k 三角形。低细节模型 (LOD5) 也有 ~5k 个顶点,但其中只有少数用于渲染 ~200 个三角形(将使用 ~2% 的数据)。

你见过这个吗?有没有道理?用于渲染大量少数多边形模型的大型数据是否会导致性能下降?

在你问之前:

网格是在运行时使用 gpu(另一个画布)生成的。生成 5 个 LOD 作为某种 mipmap(我的意思是使用画布中的最大值在像这样 http://upload.wikimedia.org/wikipedia/commons/e/ed/Mipmap_illustration2.png 这样的一次渲染中完成所有操作)仍然至少是仅生成 LOD1 的两倍。在我的情况下,索引的优势是它们可以初始化而不是在运行时生成。

一般来说,

更少的WebGL调用=更快。因此,例如,如果每个模型的每个模型属性都位于不同的缓冲区中,假设每个模型都有位置、法线、特斯科坐标、顶点颜色。让我们假设我们正在使用索引顶点。然后,要设置绘图调用,至少需要调用 9 个函数

for each model
  gl.bindBuffer(gl.ARRAY_BUFFER, model.positionBuffer);
  gl.vertexAttribPointer(model.positionLocation, ...);
  gl.bindBuffer(gl.ARRAY_BUFFER, model.normalBuffer);
  gl.vertexAttribPointer(model.normalLocation, ...);
  gl.bindBuffer(gl.ARRAY_BUFFER, model.texcoordBuffer);
  gl.vertexAttribPointer(model.texcoordLocation, ...);
  gl.bindBuffer(gl.ARRAY_BUFFER, model.vertexColorBuffer);
  gl.vertexAttribPointer(model.vertexColorLocation, ...);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.indexBuffer);
  ...
  gl.drawElements(...);

如果所有这些属性都在同一个缓冲区中,则减少到 6 个函数

for each model
  gl.bindBuffer(gl.ARRAY_BUFFER, model.buffer);
  gl.vertexAttribPointer(model.positionLocation, ...);
  gl.vertexAttribPointer(model.normalLocation, ...);
  gl.vertexAttribPointer(model.texcoordLocation, ...);
  gl.vertexAttribPointer(model.vertexColorLocation, ...);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.indexBuffer);
  ...
  gl.drawElements(...);

如果所有模型都在同一个缓冲区中,但需要的偏移量只会略微减少。现在是 5 个函数

gl.bindBuffer(gl.ARRAY_BUFFER, model.buffer);
for each model
  gl.vertexAttribPointer(model.positionLocation, ...);
  gl.vertexAttribPointer(model.normalLocation, ...);
  gl.vertexAttribPointer(model.texcoordLocation, ...);
  gl.vertexAttribPointer(model.vertexColorLocation, ...);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.indexBuffer);
  ...
  gl.drawElements(...);

相反,如果所有模型都使用来自相同缓冲区的索引,那么它会进一步减少到0个函数

gl.bindBuffer(gl.ARRAY_BUFFER, model.buffer);
gl.vertexAttribPointer(model.positionLocation, ...);
gl.vertexAttribPointer(model.normalLocation, ...);
gl.vertexAttribPointer(model.texcoordLocation, ...);
gl.vertexAttribPointer(model.vertexColorLocation, ...);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.indexBuffer);
for each model
  ...
  gl.drawElements(..., model.indexOffset);

当然,这是0用于设置属性。您仍然可能会打几个电话来设置制服。

所以,从理论上讲,这会更快。但是,这实际上假设设置绘图是您的瓶颈。瓶颈往往在其他地方。比如 GPU(绘制像素)或其他类似碰撞或物理的东西。

当然,每一点都有帮助,所以使用索引来分离模型并将所有其他数据放在巨大的缓冲区中是否是一场胜利取决于您。这听起来像PITA,对我来说不值得,但这只是我的意见

需要注意的一点是,WebGL默认只支持16位索引。有一个扩展允许32位索引,根据 webglstats.com 它在运行WebGL的95%的机器上可用。

最新更新