Класс 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 после каждой перерисовки, будет блокироваться и ожидать синхронизации по вертикали. Это означает, что всякий раз, когда выполняется обмен, обновление можно планировать повторно, вызывая 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(), который перерисовывает только меньшую область за раз, так как предыдущее содержимое сохраняется. |
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.15/qopenglwindow.html