Класс QOpenGLWindow
Класс QOpenGLWindow — это удобный подкласс QWindow для выполнения отрисовки OpenGL. Подробнее...
| Заголовок: | #include <QOpenGLWindow> |
| qmake: | QT += gui |
| С момента: | Qt 5.4 |
| Наследует: | QPaintDeviceWindow |
Этот класс был представлен в Qt 5.4.
Общедоступные типы
| перечисление | 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, и аналогичным устаревшему QGLWidget. В отличие от 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 или устаревшему QGLWidget. В противоположность этому, 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(), будет направлено на этот буфер. Этот буфер затем копируется на буфер кадра по умолчанию для поверхности окна после каждого перерисовки. Это позволяет использовать код рисования на основе QPainter в paintGL(), который перерисовывает только меньшую область за раз, потому что, в отличие от NoPartialUpdate, предыдущее содержимое сохраняется. |
QOpenGLWindow::PartialUpdateBlend |
2 |
Аналогично PartialUpdateBlit, но вместо использования копирования буфера кадра содержимое дополнительного буфера кадра рендерится путём рисования текстурированного квада с включенным смешиванием. Это, в отличие от 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] 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. Если более нет основного окна, вместо него используется офскрин-поверхность. Это гарантирует, что операции очистки ресурсов 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() не нужно, так как это уже сделано при вызове этого метода.
Перед вызовом этого метода контекст и буфер кадра (если он есть) привязываются, а порт вывода настраивается с помощью вызова 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-5.14/qopenglwindow.html