Как уменьшить отставание в OpenGl? - PullRequest
0 голосов
/ 14 февраля 2020

Я написал небольшое приложение, которое заменяет курсор нарисованным от руки курсором. Для этого я использовал QOpenGlWidget. Для анимации я использую сигнал frameSwapped:

connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));

До сих пор я не использую какую-либо конкретную c функцию OpenGl, поэтому я просто переопределяю аналог paintevent на classi c QWidget.

Документация Qt :

При выполнении рисования только с использованием QPainter рисование также можно выполнить так же, как это делается для обычных виджетов: переопределив paintEvent ().

void Widget::paintEvent(QPaintEvent* event) {


    // Draw Cursor
    POINT LpPoint;
    GetCursorPos(&LpPoint);
    QPoint CursorPos(LpPoint.x, LpPoint.y);
    CursorPos = mapFromGlobal(CursorPos);
    QPainter Painter(this);
    Painter.drawEllipse(CursorPos, 20, 20);


}

Я снял результат с 240 кадрами в секунду и понял, что мой нарисованный курсор находится на 2 кадра за курсором windows. Неважно, что лагов вообще нет. Но был бы хорош только один кадр. И было бы здорово, если бы я мог количественно определить отставание. Так что я знаю, что это один кадр + - продолжительность рендеринга. Я уже прочитал это , но я не совсем знаком с OpenGl. И я не думаю, что смогу использовать это с QOpenGlWidget. Может быть, у кого-то есть идея, как уменьшить задержку до одного кадра.

Обновление 1 : Я провел небольшое исследование и много пытался с умеренным успехом. Моя последняя версия:

connect(this, SIGNAL(frameSwapped()), this, SLOT(animate()));
void Widget::animate() {
    makeCurrent();
    QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
    f->glFinish();
    //std::this_thread::sleep_for(std::chrono::milliseconds(12));
    update();
}

Я использую glFini sh () для синхронизации c CPU и GPU. Теперь нарисованный курсор находится примерно на один кадр позади. Иногда это даже лучше, чем один кадр. Но есть пропущенные кадры, поэтому нарисованный курсор вообще не двигается. В целом нет согласованности. У меня все еще есть некоторые проблемы с пониманием того, как именно обновляется OpenGl. Может быть, немного больше информации: setIntervall установлен в 1, и это с двойной буферизацией. Я думаю, может быть, это проблема, не знаю, что именно делает Qt. Вызов update только планирует обновление, и я не могу контролировать, как буферы переставляются. Может быть, у кого-то есть больше опыта по этим вопросам. Я могу сказать, что paintevent / paintGL вызывается каждые 16 мс. Я добавил std::this_thread::sleep_for(std::chrono::milliseconds(12));, чтобы уменьшить задержку между рендером и фактическим положением мыши. Это помогает уменьшить среднюю задержку. Но для меня почти невозможно сделать прогноз solid о том, что произойдет в следующем кадре.

Обновление 2: Я опубликовал похожую проблему на Qt forum . Хотя это и не прямой ответ, он содержит некоторую полезную информацию.

...