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