Двойная буферизация в Qt3DWindow - PullRequest
2 голосов
/ 08 апреля 2019

Мое Qt3DWindow мигает при перерисовке, и мне кажется, что двойная буферизация не работает должным образом - мне нужно что-то сделать?

Я пытался установить глобальные параметры формата поверхности setSwapBehavior(QSurfaceFormat::DoubleBuffer), но, похоже, это не помогло. Я использую QForwardRenderer по умолчанию, который описывается как рендеринг в буфер, но я не могу контролировать, когда происходит перестановка буфера

void SimulationWindow::initialiseScene()
{
    this->defaultFrameGraph()->setClearColor(m_backgroundColour);
    Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
    this->setRootEntity(rootEntity);       
    Qt3DRender::QRenderSettings *renderSettings = this->renderSettings();        
    renderSettings->setRenderPolicy(Qt3DRender::QRenderSettings::OnDemand);
}

Это единственная настройка, которую я делаю для стандартного Qt3DWindow. Использование QRenderSettings :: Always не имеет значения. У меня такое ощущение, что есть настройка, доступная либо через QFrameGraphNode, либо через QForwardRenderer, которая должна что-то исправлять, либо, возможно, существует способ прямого управления, когда происходит замена заднего буфера. Это, конечно, происходит не только когда я вызываю requestUpdate (), чего я и ожидал. Или, возможно, мне нужно использовать что-то другое, кроме QForwardRenderer, чтобы получить больше контроля.

Редактировать: Я обнаружил нечто, называемое Qt3DRender :: QNoDraw, которое выглядит обнадеживающим. Предложение в документации заключается в том, что он подключен к QClearBuffers, который является частью QForwardRenderer, но не доступен для общественности.

1 Ответ

2 голосов
/ 04 мая 2019

ОК, я почти уверен, что точно выяснил, в чем проблема. Я создал тестовую программу, основанную на примере basicshapes-cpp, где одна из фигур перекрывает другие и удаляется и перерисовывается сразу каждые 0,5 секунды. Все это должно происходить в заднем буфере и не должно быть видно, но на самом деле это вызывает случайное мерцание.

Дополнительный код в main.cpp

view->renderSettings()->setRenderPolicy(Qt3DRender::QRenderSettings::OnDemand);
modifier->setView(view);
QTimer *timer = new QTimer(widget);
QObject::connect(timer, SIGNAL(timeout()), modifier, SLOT(timer()));
timer->start(500);

Дополнительный код в scenemodifier.cpp

void SceneModifier::timer()
{
    if (!m_torusEntity) return;
    delete m_torusEntity;

    // Torus shape data
    m_torus = new Qt3DExtras::QTorusMesh();
    m_torus->setRadius(1.0f);
    m_torus->setMinorRadius(0.4f);
    m_torus->setRings(100);
    m_torus->setSlices(20);

    // TorusMesh Transform
    Qt3DCore::QTransform *torusTransform = new Qt3DCore::QTransform();
    torusTransform->setScale(m_torusScale);
    torusTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(0.0f, 1.0f, 0.0f), 25.0f));
    torusTransform->setTranslation(QVector3D(5.0f, 4.0f, 0.0f));

    Qt3DExtras::QPhongMaterial *torusMaterial = new Qt3DExtras::QPhongMaterial();
    torusMaterial->setDiffuse(QColor(QRgb(0xbeb32b)));

    // Torus
    m_torusEntity = new Qt3DCore::QEntity(m_rootEntity);
    m_torusEntity->addComponent(m_torus);
    m_torusEntity->addComponent(torusMaterial);
    m_torusEntity->addComponent(torusTransform);

    m_view->requestUpdate();

}

Дополнительный код в scenemodifier.h

public slots:
    void timer();
    float m_torusScale = 4.0;
    Qt3DExtras::Qt3DWindow *m_view;
    void setView(Qt3DExtras::Qt3DWindow *view);

И вот оно. Он не мерцает все время, но время от времени он перерисовывается синхронно с заменой буфера, и вы получаете мерцание. В моем приложении рисунок намного сложнее и медленнее, а мерцание намного хуже.

enter image description here

...