Класс 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()
Этот сигнал испускается после потенциально блокирующей операции обмена буферов buffer swap. Приложения, которые хотят непрерывно перерисовывать изображение, синхронизируясь с вертикальной частотой обновления, должны вызывать 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.
END_OF_DOCUMENT_MARKER
[override virtual protected] void QOpenGLWindow::resizeEvent(QResizeEvent *event)
Реализует: QWindow::resizeEvent(QResizeEvent *ev).
Обработчик события изменения размера event. Вызывает 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.13/qopenglwindow.html