【问题标题】:Why is instanced array slower than glDrawElement?为什么实例化数组比 glDrawElement 慢?
【发布时间】:2013-06-09 22:44:38
【问题描述】:

在我的程序中,我想绘制许多球体。 首先,我为球体创建顶点、索引,然后将它们绑定到 voa/vbo/ibo。 之后,我创建了 1000 个随机模型矩阵。 现在我有两种方法来绘制网格。

  1. 只需通过调用glDrawElements 的ModelMatrices 列表循环1000 次。哪里矩阵 MVP 在 CPU 上计算并像统一一样发送到着色器。
  2. 将所有矩阵绑定到额外的 VBO 并将它们发送到着色器,如“in” 多变的。然后使用glDrawElementsInstanced 调用一次。

在测试程序中,我绘制了 1000 个球体(大约 2000 万个顶点) 当我使用第一种方法时,我得到大约 27FPS,而第二种方法将性能降低到 19FPS。理论上第二种方法应该比第一种方法获得更好的性能。

这里是代码。

我认为瓶颈是顶点着色器(VP * ModelMatrix) 中的这种乘法,因为它需要为每个(网格中的顶点)*1000 完成。

什么可以升级,我做错了什么?

【问题讨论】:

  • 每个球体 20.000 个顶点?!
  • 正好 19802 个顶点。它是非常圆的球体 :) 这是我用于创建球体顶点所需的顶点数=(slices*2)*(stacks-1)+2;跨度>
  • @user1075940 一个非常圆的球体,你通常通过正确的照明而不是使用大量的顶点来获得。

标签: c++ opengl glsl


【解决方案1】:

实例化并不总是一种胜利。这是您必须分析的那种优化,看看它是否值得做。

一般来说,如果您要渲染大量实例(1000 相当多,但还不够。想想 10,000),其中包含适度数量的顶点(20,000 可能太多了。更多地查看 100 -3000 左右)。此外,您的每个实例的数据不必要地大;当您可以轻松使用向量和四元数时,您会使用矩阵。

实例化的目的是减少CPU 开销。特别是每次绘制调用的 CPU 开销和状态更改。总共有 2000 万个顶点,1000 次绘制调用和状态更改的 CPU 开销很有可能不是您最大的问题。

【讨论】:

    【解决方案2】:

    因为你有旋转不变的球体,你可以用一个简单的平移 vec3 替换你的矩阵(也许用 w = uniform scale ?)。我不确定它会改变什么,不过,你很少受 ALU 约束。但是 20M 的顶点已经不少了。

    1000个draw call/frame在PC可以处理的范围之内(一般应该

    至于实例化的性能不佳,我真的不知道,但我怀疑这与您高达 20k 的顶点/网格有关。实例化是为相当小的网格设计的,所以 GPU 可能无法处理得很好。您可以尝试在关闭 Vsync 的情况下与较小的网格(200 个顶点)进行比较吗?我很好奇。

    【讨论】:

    • 不幸的是,我也对旋转感兴趣,这就是我传递矩阵的原因。
    • 好吧,我已经按照你说的做了。我渲染了 200000 个 182 个顶点的球体,实例化性能要好得多,大约 10-11FPS 而循环 0.5-1FPS
    • 感谢您提供的数字!有道理 =)
    • 请注意:但不要使用 FPS 作为比较的度量,因为它是必不可少的非线性度量,所以会令人困惑。您应该改用渲染帧所需的时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-15
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 2014-08-19
    • 2014-08-10
    相关资源
    最近更新 更多