【问题标题】:(python) pygame opengl is much slower than blitting(python) pygame opengl 比 blitting 慢得多
【发布时间】:2014-06-09 01:08:40
【问题描述】:

我刚刚在我的 pygame 应用程序中实现了基本的 opengl 渲染,我认为硬件加速会使程序运行得更快。相反,它要慢得多。

看起来问题出在绘图功能上。

这是我的opengl绘图功能

    def draw(self, screen):
        rect = self.texture.imagerect.copy()
        rect.x += self.xoffset
        rect.y += self.yoffset

        halfWidth = self.getWidth()/2
        halfHeight = self.getHeight()/2

        glEnable(GL_TEXTURE_2D)

        glBindTexture(GL_TEXTURE_2D, self.texture.getTexID()) 

        self.color.setGLColor()

        glPushMatrix()

        glTranslatef(rect.x,rect.y,0)

        glRotatef(self.angle, 0, 0, 1);

        glBegin(GL_QUADS)

        glTexCoord2d(0,0)
        glVertex2f(-halfWidth + self.pivot.x, -halfHeight + self.pivot.y)

        glTexCoord2d(0,1)
        glVertex2f(-halfWidth + self.pivot.x,-halfHeight + self.getHeight() + self.pivot.y)

        glTexCoord2d(1,1) 
        glVertex2f(-halfWidth + self.getWidth() + self.pivot.x,-halfHeight + self.getHeight() + self.pivot.y)

        glTexCoord2d(1,0)
        glVertex2f(-halfWidth + self.getWidth() + self.pivot.x,-halfHeight + self.pivot.y)

        glEnd()

        glPopMatrix()

我的分析器为绘图功能提供了什么

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
312792   20.395    0.000   34.637    0.000 image.py:61(draw)

我的探查器文本的其余部分:(1 个月后到期)

http://pastebin.com/ApfiCQzw

我的源代码

https://bitbucket.org/claysmithr/warbots/src

注意:当我将其设置为不绘制任何图块时,我得到 60 fps!如果我限制只绘制出现在屏幕上的图块,我也可以获得 20 fps,但这仍然比 blitting 慢得多

我尝试绘制的图块数 (64x64):15,625

有什么方法可以测试我是否真的是硬件加速的?

我应该回到 blitting 吗?

edit:blitting 不会自动绘制不在屏幕上的图块吗?这可能是opengl如此缓慢的原因!

【问题讨论】:

  • 如果您关心性能,您所做的一些事情会有些奇怪。最重要的是,您将纹理坐标作为双精度传递。 1.0 并不比 1.0f 更精确,但是 GL 必须将 1.0 转换为单精度,这样会浪费 CPU 周期。

标签: opengl pygame


【解决方案1】:

如果我理解正确的话,您需要在每一帧中绘制数千个带纹理的四边形。减速来自您为每个四边形进行的多个 OpenGL 调用 - 在上面的代码中至少有 16 个。

您需要做的是分批绘制,一次绘制更多图元。

首先,您可以将图块合并成更大的单元吗?过去十年制造的任何显卡都可以处理 16K x 16K 纹理贴图。无需绑定新纹理即可绘制的四边形越多越好。

用顶点数组替换 glBegin .. glEnd 块。即使在一次仍然绘制一个四边形的最坏情况下,您也可以将当前的 10 个 OpenGL 调用替换为仅 2 个 glVertexPointer 和 glTexCoordPointer。

然后开始将平铺四边形合并到更大的顶点数组中。不要使用 glTranslatef,而是将 rect.x 和 rect.y 值直接添加到每个顶点。

glRotatef 是一个问题,如果它确实必须为每个图块不同。如果它仅限于 90 度的倍数,那么您就不需要它,只需交换纹理坐标即可。对于其他值,请研究如何使用 sin 和 cos 直接旋转纹理坐标。

一旦您消除了每个图块的平移和旋转,您可以将所有计算出的四边形顶点和纹理坐标粘贴到巨大的顶点数组中,只需两次调用即可绘制整个地图。

希望这会有所帮助。

(对于真正的超性能,您可能希望使用 GPU 端顶点缓冲区对象和着色器,但从您的编码风格来看,我假设您想坚持使用 OpenGL 1/2。)

【讨论】:

    猜你喜欢
    • 2020-02-12
    • 2018-07-14
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多