Класс QOpenGLWindow
Класс QOpenGLWindow — это удобный подкласс QWindow для выполнения рисования с помощью OpenGL. Подробнее...
| Заголовок: | #include <QOpenGLWindow> |
| CMake: | find_package(Qt6 COMPONENTS OpenGL REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::OpenGL) |
| qmake: | QT += opengl |
| С момента: | Qt 5.4 |
| Наследует: | QPaintDeviceWindow |
Типы публичного доступа
| перечисление | UpdateBehavior { NoPartialUpdate, PartialUpdateBlit, PartialUpdateBlend } |
Функции публичного доступа
| QOpenGLWindow(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr) | |
| QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr) | |
| виртуальный | ~QOpenGLWindow() |
| QOpenGLContext * | context() const |
| GLuint | defaultFramebufferObject() const |
| void | doneCurrent() |
| QImage | grabFramebuffer() |
| bool | isValid() const |
| void | makeCurrent() |
| QOpenGLContext * | shareContext() const |
| QOpenGLWindow::UpdateBehavior | updateBehavior() const |
Сигналы
| void | frameSwapped() |
Защищённые функции
| виртуальный void | initializeGL() |
| виртуальный void | paintGL() |
| виртуальный void | paintOverGL() |
| виртуальный void | paintUnderGL() |
| виртуальный void | resizeGL(int w, int h) |
Переопределённые защищённые функции
| виртуальный void | paintEvent(QPaintEvent *event) override |
| виртуальный void | resizeEvent(QResizeEvent *event) override |
Подробное описание
QOpenGLWindow — это расширенный класс QWindow, позволяющий легко создавать окна, выполняющие рендеринг OpenGL с помощью API, совместимого с QOpenGLWidget В отличие от QOpenGLWidget, QOpenGLWindow не зависит от модуля виджетов и обеспечивает лучшую производительность.
Типичное приложение наследует от QOpenGLWindow и переопределяет следующие виртуальные функции:
- initializeGL() для инициализации ресурсов OpenGL
- resizeGL() для настройки матриц преобразования и других ресурсов, зависящих от размера окна
- paintGL() для выполнения команд OpenGL или рисования с помощью QPainter
Для планирования перерисовки вызовите функцию update(). Обратите внимание, что это не сразу приведёт к вызову paintGL(). Вызов update() несколько раз подряд не изменит поведение никоим образом.
Это слот, поэтому его можно подключить к сигналу QTimer::timeout() для выполнения анимации. Однако в современном мире OpenGL гораздо лучшим выбором является использование синхронизации с частотой вертикальной развертки экрана. См. setSwapInterval() для описания интервала обмена. С интервалом обмена 1, который используется по умолчанию на большинстве систем, вызов swapBuffers(), выполняемый внутренне QOpenGLWindow после каждой перерисовки, будет блокироваться и ждать vsync. Это означает, что всякий раз, когда обмен выполняется, можно снова запланировать обновление, вызвав update(), не полагаясь на таймеры.
Для запроса конкретной конфигурации контекста используйте setFormat(), как и для любого другого QWindow. Это позволяет, среди прочего, запросить определённую версию и профиль OpenGL или включить буферы глубины и трафарета.
В отличие от QWindow, QOpenGLWindow позволяет открыть рисовальщик на себе и выполнить рисование на основе QPainter.
QOpenGLWindow поддерживает несколько стратегий обновления. По умолчанию, NoPartialUpdate соответствует стандартному окну OpenGL на основе QWindow. В отличие от этого, PartialUpdateBlit и PartialUpdateBlend больше соответствуют работе QOpenGLWidget, где всегда присутствует дополнительный выделенный буфер кадра. Эти режимы позволяют, в ущерб производительности, перерисовывать только меньшую область при каждом рисовании, сохраняя при этом содержимое предыдущего кадра. Это полезно для приложений, которые выполняют рендеринг по частям с использованием QPainter, поскольку таким образом им не нужно перерисовывать всё содержимое окна при каждом вызове paintGL().
Так же, как и QOpenGLWidget, QOpenGLWindow поддерживает атрибут Qt::AA_ShareOpenGLContexts. При включении контексты OpenGL всех экземпляров QOpenGLWindow будут совместно использоваться. Это позволяет получать доступ к общим ресурсам OpenGL друг друга.
Дополнительную информацию о графике в Qt см. в разделе Графика.
Документация по типам членов
перечисление QOpenGLWindow::UpdateBehavior
Это перечисление описывает стратегию обновления QOpenGLWindow.
| Константа | Значение | Описание |
|---|---|---|
QOpenGLWindow::NoPartialUpdate |
0 |
Указывает, что вся поверхность окна будет перерисована при каждом обновлении, поэтому дополнительные буферы кадров не нужны. Это значение используется в большинстве случаев и эквивалентно тому, как бы работало рисование напрямую через QWindow. |
QOpenGLWindow::PartialUpdateBlit |
1 |
Указывает, что рисование, выполненное в paintGL(), не охватывает всё окно. В этом случае под капотом создаётся дополнительный буфер кадра, и рендеринг, выполняемый в paintGL(), будет нацелен на этот буфер. Этот буфер затем «сливается» (blitted) на стандартный буфер кадра поверхности окна после каждого рисования. Это позволяет иметь код рисования на основе QPainter в paintGL(), который перерисовывает только меньшую область за раз, потому что, в отличие от NoPartialUpdate, предыдущее содержимое сохраняется. |
QOpenGLWindow::PartialUpdateBlend |
2 |
Подобно PartialUpdateBlit, но вместо использования слияний (blits) содержимое дополнительного буфера кадра отрисовывается путём рисования текстурированной четырёхугольной области с включённым смешиванием (blending). Это, в отличие от PartialUpdateBlit, позволяет использование альфа-смешивания и работает даже тогда, когда glBlitFramebuffer недоступен. С точки зрения производительности этот параметр, скорее всего, будет несколько медленнее, чем PartialUpdateBlit. |
Документация по функциям-членам
QOpenGLWindow::QOpenGLWindow(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)
Конструирует новый QOpenGLWindow с заданным parent и updateBehavior. Контекст QOpenGLWindow будет совместно использоваться с shareContext.
См. также QOpenGLWindow::UpdateBehavior и shareContext.
QOpenGLWindow::QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)
Создаёт новый QOpenGLWindow с заданным parent и updateBehavior.
См. также QOpenGLWindow::UpdateBehavior.
[signal] void QOpenGLWindow::frameSwapped()
Этот сигнал генерируется после потенциально блокирующего обмена буферами. Приложения, которые хотят непрерывно перерисовывать, синхронизируясь с вертикальной частотой обновления, должны вызвать update() при поступлении этого сигнала. Это позволяет добиться намного более плавного отображения по сравнению с традиционным использованием таймеров.
[virtual, since 5.5] QOpenGLWindow::~QOpenGLWindow()
Уничтожает экземпляр QOpenGLWindow, освобождая его ресурсы.
Контекст OpenGLWindow делается текущим в деструкторе, что позволяет безопасно уничтожить любой дочерний объект, которому может потребоваться освободить ресурсы OpenGL, принадлежащие контексту, предоставляемому этим окном.
Предупреждение: если у вас есть объекты, оборачивающие ресурсы OpenGL (такие как QOpenGLBuffer, QOpenGLShaderProgram и т. д.) в качестве членов подкласса QOpenGLWindow, вам может потребоваться добавить вызов makeCurrent() также в деструкторе этого подкласса. Из-за правил уничтожения объектов C++, эти объекты будут уничтожены до вызова этой функции (но после того, как выполнится деструктор подкласса), поэтому приведение контекста OpenGL в текущее состояние в этой функции происходит слишком поздно для их безопасного удаления.
Эта функция была добавлена в Qt 5.5.
См. также makeCurrent.
QOpenGLContext *QOpenGLWindow::context() const
Возвращает QOpenGLContext, используемый этим окном, или 0 если он ещё не инициализирован.
GLuint QOpenGLWindow::defaultFramebufferObject() const
Обработчик объекта фреймбуфера, используемый этим окном.
Когда поведение обновления установлено в NoPartialUpdate, отдельный объект фреймбуфера отсутствует. В этом случае возвращаемое значение является идентификатором стандартного фреймбуфера.
В противном случае значение идентификатора объекта фреймбуфера или 0 если он ещё не инициализирован.
void QOpenGLWindow::doneCurrent()
Освобождает контекст.
В большинстве случаев вызывать эту функцию не нужно, так как виджет позаботится о правильной привязке и освобождении контекста при вызове paintGL().
См. также makeCurrent().
QImage QOpenGLWindow::grabFramebuffer()
Возвращает копию фреймбуфера.
Примечание: это потенциально дорогостоящая операция, так как она использует glReadPixels() для чтения пикселей обратно. Это может быть медленным и может остановить конвейер GPU.
Примечание: При использовании вместе с поведением обновления NoPartialUpdate, возвращаемое изображение может не содержать нужного содержимого, если оно вызывается после того, как передние и задние буферы были поменены (если в интерфейсе системного окна не включен сохранённый обмен). В этом режиме функция считывает из заднего буфера, и содержимое может не соответствовать содержимому на экране (передний буфер). В этом случае единственное место, где эта функция может безопасно использоваться, это paintGL() или paintOverGL().
[virtual protected] void QOpenGLWindow::initializeGL()
Эта виртуальная функция вызывается один раз перед первым вызовом paintGL() или resizeGL(). Переопределите её в подклассе.
В этой функции должны быть настроены все необходимые ресурсы и состояние OpenGL.
Нет необходимости вызывать makeCurrent(), поскольку это уже сделано при вызове этой функции. Тем не менее, обратите внимание, что фреймбуфер в случае использования частичного обновления ещё недоступен на этом этапе, поэтому избегайте вызова функций отрисовки отсюда. Отложите такие вызовы на paintGL() вместо этого.
См. также paintGL() и resizeGL().
bool QOpenGLWindow::isValid() const
Возвращает true , если ресурсы OpenGL окна, такие как контекст, были успешно инициализированы. Обратите внимание, что возвращаемое значение всегда false до тех пор, пока окно не станет видимым.
void QOpenGLWindow::makeCurrent()
Подготавливает к отрисовке контента OpenGL для этого окна, делая соответствующий контекст текущим и связывая объект фреймбуфера, если он есть, в этом контексте.
В большинстве случаев вызывать эту функцию не нужно, так как она вызывается автоматически перед вызовом paintGL(). Тем не менее, она предоставлена для поддержки сложных многопоточных сценариев, когда поток, отличный от потока GUI или основного потока, может захотеть обновить содержимое поверхности или фреймбуфера. См. QOpenGLContext для получения дополнительной информации о связанных с потоками проблемах.
Эта функция также подходит для вызова, когда подлежащее платформенное окно уже уничтожено. Это означает, что эту функцию можно безопасно вызывать из деструктора подкласса QOpenGLWindow. Если родное окно больше не существует, вместо него используется поверхностный объект offscreen. Это гарантирует, что операции очистки ресурсов OpenGL в деструкторе всегда будут работать, если эта функция вызывается первой.
См. также QOpenGLContext, context(), paintGL() и doneCurrent().
[override virtual protected] void QOpenGLWindow::paintEvent(QPaintEvent *event)
Переопределяет: QPaintDeviceWindow::paintEvent(QPaintEvent *event).
Обработчик события event. Вызывает paintGL().
См. также paintGL().
[virtual protected] void QOpenGLWindow::paintGL()
Эта виртуальная функция вызывается всякий раз, когда требуется перерисовать содержимое окна. Переопределите её в подклассе.
Нет необходимости вызывать makeCurrent(), поскольку это уже сделано при вызове этой функции.
Перед вызовом этой функции контекст и фреймбуфер (если он есть) привязываются, и viewport настраивается с помощью вызова glViewport(). Никакое другое состояние не устанавливается, и никакое очищение или отрисовка не выполняются фреймворком.
Примечание: При использовании режима частичного обновления, например, PartialUpdateBlend, вывод предыдущего вызова paintGL() сохраняется, и после дополнительной отрисовки, выполненной в текущем вызове функции, содержимое копируется или накладывается поверх содержимого, нарисованного непосредственно в окне в paintUnderGL().
См. также initializeGL(), resizeGL(), paintUnderGL(), paintOverGL() и UpdateBehavior.
[virtual protected] void QOpenGLWindow::paintOverGL()
Эта виртуальная функция вызывается после каждого вызова paintGL().
Когда режим обновления установлен на NoPartialUpdate, между этой функцией и paintGL() нет разницы; отрисовка в любой из них приводит к одному и тому же результату.
Как и paintUnderGL(), отрисовка в этой функции направлена на основной фреймбуфер окна, независимо от поведения обновления. Она вызывается после того, как paintGL() вернулась и выполнена копирование (PartialUpdateBlit) или отрисовка четырехугольника (PartialUpdateBlend).
См. также paintGL(), paintUnderGL() и UpdateBehavior.
[virtual protected] void QOpenGLWindow::paintUnderGL()
Виртуальная функция вызывается перед каждым вызовом paintGL().
Когда режим обновления установлен на NoPartialUpdate, между этой функцией и paintGL() нет разницы; отрисовка в любой из них приводит к одному и тому же результату.
Разница становится значительной при использовании PartialUpdateBlend, где используется дополнительный объект фреймбуфера. Там paintGL() направлена на этот дополнительный объект фреймбуфера, который сохраняет его содержимое, в то время как paintUnderGL() и paintOverGL() направлены на основной фреймбуфер, то есть непосредственно на поверхность окна, содержимое которого теряется после каждого отображаемого кадра.
Примечание: Избегайте полагания на эту функцию, когда поведение обновления установлено на PartialUpdateBlit. Этот режим включает копирование дополнительного фреймбуфера, используемого paintGL(), в основной фреймбуфер после каждого вызова paintGL(), тем самым перезаписывая всю отрисовку, сгенерированную в этой функции.
См. также paintGL(), paintOverGL() и UpdateBehavior.
[override virtual protected] void QOpenGLWindow::resizeEvent(QResizeEvent *event)
Переопределяет: QWindow::resizeEvent(QResizeEvent *ev).
Обработчик события изменения размера. Вызывает resizeGL().
См. также resizeGL().
[virtual protected] void QOpenGLWindow::resizeGL(int w, int h)
Этот виртуальный метод вызывается всякий раз, когда виджет был изменен. Переопределите его в подклассе. Новый размер передаётся в w и h.
Примечание: Это всего лишь удобная функция для обеспечения совместимости API с QOpenGLWidget. В отличие от QOpenGLWidget, производные классы могут выбрать переопределение resizeEvent() вместо этой функции.
Примечание: Избегайте выполнения команд OpenGL из этой функции, так как контекст может отсутствовать при её вызове. Если этого избежать нельзя, вызовите makeCurrent().
Примечание: Планирование обновлений отсюда не требуется. Системы оконного интерфейса отправят события expose, которые автоматически вызовут обновление.
См. также initializeGL() и paintGL().
QOpenGLContext *QOpenGLWindow::shareContext() const
Возвращает QOpenGLContext, который требуется для совместного использования с QOpenGLContext этого окна.
QOpenGLWindow::UpdateBehavior QOpenGLWindow::updateBehavior() const
Возвращает поведение обновления для этого QOpenGLWindow.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qopenglwindow.html