QOpenGLWidget中的动画看起来很迟钝

时间:2016-04-09 17:49:37

标签: c++ qt animation opengl vsync

我没有写游戏的经验,本周我正在尝试在QT中写一个音乐游戏地图的玩家(最终可能成为游戏?);遇到问题,我想我需要一些帮助。

我想在QOpenGLWidget上以60 FPS显示动画。只是一些圈子在小部件中移动,CPU使用率很低。但它看起来很迟钝。

我通过将默认表面格式的交换行为设置为doublebuffer / triplebuffer来启用VSync,并且间隔为1,我认为这意味着60 FPS。
我实现了paintGL()方法并通过QT的2D绘图示例所做的QPainter绘制内容。
计算每个圆的位置的步骤放在paintGL方法之外,并且在调用paintGL之前运行。

这是程序运行的流程:

  1. 阅读脚本
  2. 启动计时器
  3. 发布一个事件来调用“tick”程序
  4. “tick”程序运行,请求更新窗口。
  5. paintGL运行,绘制框架
  6. 在退出paintGL方法之前,会发布一个名为“tick”的事件
  7. 我认为现在它等待VSync和交换缓冲区
  8. 调用“tick”,转到第4步
  9. 代码:

    class CgssFumenPlayer : public QOpenGLWidget
    {
        Q_OBJECT
    
        ...
        bool Load();
    
    public slots:
        void onTick();
    
    protected:
        ....
        void paintGL() override;
        QElapsedTimer elapsedTimer;
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QSurfaceFormat fmt;
        fmt.setSwapBehavior(QSurfaceFormat::TripleBuffer);
        fmt.setSwapInterval(1);
        QSurfaceFormat::setDefaultFormat(fmt);
    
        CgssFumenPlayer w;
        w.Load();
        w.setFixedSize(704, 396);
        w.show();
    
        return a.exec();
    }
    
    bool CgssFumenPlayer::Load()
    {
        ....
        elapsedTimer.start();
        QMetaObject::invokeMethod(this, "onTick", Qt::QueuedConnection);
    }
    
    void CgssFumenPlayer::onTick()
    {
        playerContext.currentTime = elapsedTimer.elapsed() / 1000.0;
        double f = playerContext.currentTime / (1.0 / 60);
        playerContext.currentTime = (int)f * (1.0 / 60);
    
        fumen->Compute(&playerContext);
    
        update();
    }
    
    
    void CgssFumenPlayer::paintGL()
    {
        QPainter painter;
        painter.begin(this);
    
        painter.setRenderHint(QPainter::Antialiasing);
    
        painter.setWindow(0, 0, windowWidth, windowHeight);
        painter.fillRect(QRectF(0, 0, windowWidth, windowHeight), QColor().black());
        DrawButtons(painter);
        DrawIcons(painter, &playerContext);
    
        painter.end();
    
        QMetaObject::invokeMethod(this, "onTick", Qt::QueuedConnection);
    }
    

    我尝试了这些方法来获取更多信息:

    1. 每次进入paintGL方法时,通过qDebug()打印当前时间。
      似乎有时框架被丢弃;它看起来非常明显,并且它与上次调用时间间隔超过30毫秒。
    2. 将鼠标移入/移出窗口持续时间动画。它的可能性越来越大。
    3. 收集计算位置的时间成本,似乎只是很短的时间。
    4. 在android中运行这个程序,只是相同甚至更加滞后。
    5. 比较复杂的游戏在我的电脑上运行得很流畅。我认为硬件足够快。 (i7-4800M,GTX 765M)
    6. 一次又一次重启程序。它现在流畅(发生了更少或没有丢帧),现在有点迟了......我找不到模式。
    7. 此外,将动画调整为30 FPS,因为它总是看起来很迟钝。

      我该如何处理这个问题?
      (p.s.我希望它也能在Android上运行)

      这是完整的源代码

      https://github.com/sorayuki/CGSSPlayer/releases(cgssplayer.zip,不是源代码)
      (我认为cgss-fumen.cpp在这个问题上没有任何区别)

      它可以在QTCreator(5.6)中构建而没有其他依赖。

      (对于QT 5.5,需要添加

      CONFIG += c++11
      

      进入.pro文件)

0 个答案:

没有答案