【问题标题】:Speeding up the drawing of rotated and scaled images in OpenGL在 OpenGL 中加速旋转和缩放图像的绘制
【发布时间】:2011-09-05 17:37:42
【问题描述】:

我正在尝试几种绘制大量精灵的方法(例如,用于粒子系统),但我得到了一些不确定的结果。所以这就是我尝试过的和我拥有的: 完成绘制 25k 个精灵:

  1. 使用常规 glBegin/glEnd 并使用三角函数计算顶点 - 17-18fps。
  2. 使用常规的glBegin/glEnd,但使用glRotateglTranslateglScale 转换精灵 - 14-15fps。
  3. 使用顶点数组代替glBeginglEnd,但仍使用三角函数来计算顶点位置 - 10-11fps。
  4. 使用顶点数组代替glBeginglEnd,但使用glRotateglTranslateglScale 来变换精灵 - 10-11fps。

所以我的问题是,为什么使用顶点数组比使用 glBegin/glEnd 慢,而我已经读过(甚至在这里)它应该更快?

为什么使用自己的三角函数(在我的例子中是 5 cos、5 sin、超过 5 个除法、15 个乘法和大约 10 个加法/减法)比使用 5 个函数(glPushMatrix()glTranslated()glRotated()glScaled()glPopMatrix())。我虽然它们是在 GPU 上完成的,所以它应该快得多

在绘制较少的精灵时,我确实得到了更有希望的结果。就像我绘制 10k 个精灵时,顶点数组可以快 5fps 左右,但仍然不一致。另请注意,这些 fps 可以整体增加,因为我还有其他计算正在进行,所以我并不是真正关注 fps 本身,而是它们之间的差异。就像如果顶点数组和 gl 变换比手动触发的 glBegin/glEnd 多 5-10fps,那么我会很高兴,但现在看来,这似乎不值得麻烦。他们会帮助移植到 GLES(因为它没有 glBegin/glEnd),但我想我会为此做一个单独的实现。

那么有什么方法可以在不使用几何着色器的情况下加快速度?我不太了解它们(也许是一些很棒的教程?),它们可能会破坏与旧硬件的兼容性,所以我想在不使用着色器的情况下尽可能地榨取汁液。

【问题讨论】:

  • 这似乎真的很低。 CPU/GPU 规格?

标签: c++ performance opengl transform


【解决方案1】:

所以我的问题是为什么使用顶点数组比使用 glBegin/glEnd 慢,而我已经读过(甚至在这里)它应该更快?

谁说他们慢的?

您只能说,对于您的特定硬件,对于您当前的驱动程序,glBegin/glEnd 较慢。您是否在其他硬件上验证过这一点?

更重要的是,如何绘制这些是一个问题。您是否从顶点数组中绘制一个精灵,然后绘制另一个,然后再绘制另一个?或者您是否通过一个glDrawArraysglDrawElements 调用来绘制所有

如果您没有一口气画完所有这些(或至少一次画出一大组),那么您就没有达到应有的速度。

为什么使用你自己的三角函数(在我的例子中是 5 个 cos、5 个 sin、超过 5 个除法、15 个乘法和大约 10 个加法/减法)比使用 5 个函数(glPushMatrix()、glTranslated() 、glRotated()、glScaled()、glPopMatrix())。我虽然它们是在 GPU 上完成的,所以应该快很多。

好吧,让我们考虑一下。 glPushMatrix 不花钱。 glTranslated 创建一个双精度浮点矩阵,然后做一个矩阵相乘glRotated 至少做一个 sin 和一个 cos,做一些加法和减法来计算一个矩阵(都是双精度的),然后 做一个矩阵乘法glScaled 计算一个矩阵,然后做一个矩阵相乘

每个“矩阵乘法”由 16 个浮点乘法和 12 个浮点加法组成。而且由于您要求双精度数学,因此您可以忘记 SSE 矢量数学或其他任何东西;这是在做标准数学。而你正在为每个点做 3 个

在 GPU 上发生的是该矩阵与顶点位置的乘法。而且由于您在更改矩阵之前只传递了 4 个位置,因此速度较慢也就不足为奇了。

【讨论】:

  • 好的。谢谢你。我真的没有办法使用一个 glDrawArray 一次绘制所有这些,尽管我可能会以某种方式改进它。还要感谢您解释翻译的工作原理。因此,如果我在数组中放置更多顶点,它们应该会更快吗?你说“每一点”,因此当我对每个精灵单独或在组上执行此操作时,似乎不应该有速度增益。另外,我说 glBegin/glEnd 更快,而不是更慢。
  • 我想我应该明确指出@Nicol Bolas 没有逐字说明最后一段暗示的内容:glRotate、glTranslate、glScale 在 CPU 上执行,只有生成的矩阵被传输到GPU。
  • 感谢 datenwolf。这解释了很多。另外,是否可以对我绘制顶点数组的所有四边形使用一个纹理坐标?我现在正在对 Nicol 的建议进行基准测试,我尝试通过填充顶点数组来绘制 n 个精灵。我只是不想对 texcoord 数组做同样的事情,因为它应该是: GLfloat texCoords[] = {0.0, 0.0, tbx, 0.0, tbx, tby, 0.0, tby };然后重用于所有绘制的精灵。我尝试将“步幅”设置为 -sizeof(GLfloat)*4,希望它能通过坐标前进,然后返回 4 个坐标,然后再做一次,但遗憾的是这不起作用。
  • @Harry: 不允许负跨步; GLsizei,stride 参数的类型,是一个无符号整数。所以你必须为每个位置提供一个纹理坐标。
  • @Nicol Bolas - 这似乎是在浪费空间。但是没问题。现在我对其进行了测试并且它可以工作,但我想不利的一面是我不能有超过 32k 的顶点?那些是4k精灵。因为那时我的应用程序冻结了。此外,动画和移动它们可能是一个更大的挑战,但我想我可以在数组中修改它们。好消息是我可以多次绘制同一个顶点数组,所以我可以对其进行基准测试。现在我可以绘制 20k 个精灵而没有任何真正的 fps 下降(~70,因为 vsync,这对我来说是最大值)。
【解决方案2】:

您是否考虑过使用 glPoints...() 代替?这就是他们的设计目的,具体取决于您支持的 OpenGL 版本。

【讨论】:

    【解决方案3】:

    您是否尝试过 VBO?它们是当前的标准,因此大多数卡片都针对它们进行了优化。

    还有:

    • 您应该使用自己的数学计算方法
    • 考虑将尽可能多的计算卸载到着色器

    您发布的 fps 数值与人们的预期相反——您可能做错了什么。你能贴一些你的渲染代码吗?

    【讨论】:

    • 是的,我也在考虑 VBO。它们对于静态精灵来说会很快(因为你只是在纹理上绘制就可以了),但是如果我为每个精灵设置动画,那么无论如何我最终都会以某种方式绘制它们。
    【解决方案4】:

    您有使用双精度矩阵函数的特定原因吗?它们通常比单精度慢很多。

    【讨论】:

    • 我尝试了浮点精度矩阵函数,但它们似乎并没有太大(或根本没有)改变速度。可能是因为在所有事情的宏伟计划中都没有那么重要。绘制图像本身是目前缓慢的部分。但是谢谢你告诉我这个。 :) 反正我不需要双精度,所以我把它们都改成了浮点数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 2010-11-08
    相关资源
    最近更新 更多