QOpenGLWindow 类
QOpenGLWindow 类是 QWindow 的便捷子类,用于执行 OpenGL 绘画。有关更多信息,请参阅更多...
头文件 | #include <QOpenGLWindow> |
CMake | find_package(Qt6 REQUIRED COMPONENTS OpenGL) target_link_libraries(mytarget PRIVATE Qt6::OpenGL) |
qmake | QT += opengl |
继承 | QPaintDeviceWindow |
公开类型
枚举 | UpdateBehavior { NoPartialUpdate, PartialUpdateBlit, PartialUpdateBlend } |
公开函数
QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr) | |
QOpenGLWindow(QOpenGLContext *shareContext, 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,它允许使用与 QOpenGLWidget 兼容的 API 容易地创建执行 OpenGL 渲染的窗口。与 QOpenGLWidget 不同,QOpenGLWindow 不依赖于小部件模块并提供更好的性能。
一个典型的应用程序将派生自 QOpenGLWindow 并重写以下虚拟函数。
- initializeGL() 执行 OpenGL 资源初始化
- resizeGL() 设置转换矩阵和其他窗口大小相关的资源
- paintGL() 发布 OpenGL 命令或使用 QPainter 绘制
为了安排重绘,请调用update() 函数。注意,这不会立即导致调用paintGL()。连续多次调用update() 不会以任何方式改变行为。
这是一个槽,因此它可以连接到QTimer::timeout() 信号以执行动画。但是请注意,在现代OpenGL世界中,依赖于显示的垂直刷新率同步是一个更好的选择。请参阅setSwapInterval() 了解交换间隔的说明。默认情况下,大多数系统使用1
作为交换间隔,这表示每次重绘后,QOpenGLWindow都会执行swapBuffers() 调用,这将阻塞并等待vsync。这意味着每次交换完成时,都可以通过调用update() 来安排新的更新,而不依赖于计时器。
要为上下文请求特定的配置,请像对任何其他QWindow 一样使用setFormat()。这允许,例如,请求特定的OpenGL版本和配置文件,或者启用深度和模板缓冲区。
注意:应用程序负责确保从底层窗口系统接口请求深度和模板缓冲区。如果不请求非零的深度缓冲区大小,则无法保证将提供深度缓冲区,结果,与深度测试相关的OpenGL操作可能无法按预期工作。
常用的深度和模板缓冲区大小请求分别为24和8。例如,QOpenGLWindow的子类可以在其构造函数中这样做
QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); setFormat(format);
与QWindow不同,QOpenGLWindow允许在自身上打开画家并执行QPainter基于的绘图。
QOpenGLWindow支持多种更新行为。默认的NoPartialUpdate
与基于OpenGL的常规QWindow相同。相比之下,PartialUpdateBlit
和PartialUpdateBlend
更符合QOpenGLWidget的工作方式,其中始终存在一个额外的、专用的帧缓冲区对象。这些模式允许牺牲一些性能,每次绘图时只重绘更小的区域,并将其他内容从上一帧保留下来。这对于使用QPainter增量渲染的应用程序很有用,因为它这样就不需要在每次paintGL() 调用中都重绘整个窗口内容。
类似于QOpenGLWidget,QOpenGLWindow支持Qt::AA_ShareOpenGLContexts属性。启用时,所有的QOpenGLWindow实例将共享OpenGL上下文。这允许访问彼此的可共享OpenGL资源。
有关Qt图形的更多信息,请参阅图形。
成员类型文档
枚举 QOpenGLWindow::UpdateBehavior
此枚举描述了QOpenGLWindow的更新策略。
常量 | 值 | 描述 |
---|---|---|
QOpenGLWindow::NoPartialUpdate | 0 | 指示每次更新都将重绘整个窗口表面,因此不需要额外的帧缓冲区。这通常是使用的设置,并且与直接通过QWindow绘图的方式相同。 |
QOpenGLWindow::PartialUpdateBlit | 1 | 指示在 paintGL() 中执行的绘图未覆盖整个窗口。在这种情况下,后台会创建一个额外的帧缓冲区对象,而 paintGL() 中的渲染将针对这个帧缓冲区。然后在每次渲染后,将这个帧缓冲区绘制到窗口表面的默认帧缓冲区上。这允许在 paintGL() 中拥有基于 QPainter 的绘图代码,每次只重涂一个较小的区域,因为,与 NoPartialUpdate 不同,之前的内容会被保留。 |
QOpenGLWindow::PartialUpdateBlend | 2 | 类似于 PartialUpdateBlit,但不是使用帧缓冲区复制,而是通过启用混合的纹理四边形绘制,将额外帧缓冲区的内容渲染出来。这与 PartialUpdateBlit 不同,允许 Alpha 混合内容,并且即使在 glBlitFramebuffer 不可用的情况下也能正常工作。在性能方面,此设置可能比 PartialUpdateBlit 慢一些。 |
成员函数文档
[显式]
QOpenGLWindow::QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)
使用指定的 parent 和 updateBehavior 构造新的 QOpenGLWindow。
另请参阅QOpenGLWindow::UpdateBehavior。
[显式]
QOpenGLWindow::QOpenGLWindow(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr)
使用指定的 parent 和 updateBehavior 构造新的 QOpenGLWindow。QOpenGLWindow 的上下文将与 shareContext 共享。
另请参阅QOpenGLWindow::UpdateBehavior 和 shareContext。
[虚 noexcept]
QOpenGLWindow::~QOpenGLWindow()
销毁 QOpenGLWindow 实例,释放其资源。
在析构函数中,将 OpenGLWindow 的上下文设置为当前状态,这样就可以安全地销毁可能需要释放该窗口提供的上下文所属的 OpenGL 资源的任何子对象。
警告:如果您在 QOpenGLWindow 子类中将 OpenGL 资源(如 QOpenGLBuffer、QOpenGLShaderProgram 等)作为成员对象,则可能需要在子类的析构函数中添加对 makeCurrent() 的调用。由于 C++ 对象析构的规则,这些对象将在调用此函数之前被销毁(但在子类析构函数执行之后),因此在此函数中使 OpenGL 上下文变为当前状态对它们的妥善处置来说发生得太晚。
另请参阅makeCurrent。
QOpenGLContext *QOpenGLWindow::context() const
返回本窗口使用的 QOpenGLContext 或如果尚未初始化则返回 0
。
GLuint QOpenGLWindow::defaultFramebufferObject() const
本窗口使用的帧缓冲区对象句柄。
当更新行为设置为 NoPartialUpdate
时,没有单独的帧缓冲区对象。在这种情况下,返回的是默认帧缓冲区的 ID。
否则返回帧缓冲区对象的 ID 或如果尚未初始化则返回 0
。
void QOpenGLWindow::doneCurrent()
释放上下文。
大多数情况下不必调用此函数,因为小部件会确保在调用 paintGL() 时上下文被正确地绑定和释放。
另请参阅 makeCurrent。
[signal]
void QOpenGLWindow::frameSwapped()
此信号在可能阻塞的 缓冲区交换 完成后发出。希望与垂直刷新同步连续重绘的应用程序应该在接收此信号时发出 update()。这比传统定时器的使用要平滑得多。
QImage QOpenGLWindow::grabFramebuffer()
返回帧缓冲区的副本。
注意: 这是一个可能昂贵的操作,因为它依赖于 glReadPixels() 来读取像素。这可能会很慢并且可能导致 GPU 管道停滞。
注意: 当与更新行为 NoPartialUpdate
一起使用时,在前后缓冲区更换之后调用时返回的图像可能不包含所需内容(除非底层窗口系统接口启用了保留交换)。在此模式下,此函数从后缓冲区读取,其内容可能不匹配屏幕上的内容(前缓冲区)。在这种情况下,此函数唯一可以安全使用的位置是 paintGL 或 paintOverGL。
[virtual protected]
void QOpenGLWindow::initializeGL()
在调用第一个 paintGL() 或 resizeGL() 之前调用此虚拟函数一次。在子类中重写它。
此函数应设置所需的所有 OpenGL 资源和状态。
无需调用 makeCurrent,因为当调用此函数时已经完成。然而请注意,如果使用部分更新模式,那么在此阶段帧缓冲区尚未可用,因此请避免从这里发出绘制调用。将这些调用推迟到 paintGL。
bool QOpenGLWindow::isValid() const
如果窗口的 OpenGL 资源(如上下文)已成功初始化,则返回代码 true
。请注意,返回值始终为 false
,直到窗口变为可见(显示)。
void QOpenGLWindow::makeCurrent()
通过将相应的上下文设置为当前上下文并在该上下文中绑定帧缓冲区对象(如果有),为此窗口准备渲染 OpenGL 内容。
大多数情况下不需要调用此函数,因为在对 paintGL 调用之前自动调用它。尽管如此,它还是提供了支持高级的、多线程的情景,其中除了 GUI 或主线程之外的线程可能想要更新表面或帧缓冲区内容。有关有关线程相关问题的更多信息,请参阅 QOpenGLContext。
此函数还适用于在底层平台窗口已被销毁时调用。这意味着可以从QOpenGLWindow子类的析构函数中调用此函数。如果没有原生窗口了,则使用离屏表面代替。这确保了只要首次调用此函数,析构函数中的OpenGL资源清理操作总能正常工作。
另见 QOpenGLContext,context(),paintGL()和doneCurrent()。
[覆盖虚保护]
void QOpenGLWindow::paintEvent(QPaintEvent *event)
重新实现: QPaintDeviceWindow::paintEvent(QPaintEvent *event).
绘制事件处理程序。调用paintGL()。
另见 paintGL()。
[虚保护]
void QOpenGLWindow::paintGL()
此虚函数在需要绘制窗口内容时被调用。在子类中重新实现它。
不需要调用makeCurrent(),因为此操作在调用此函数时已经完成。
在调用此函数之前,通过调用glViewport()设置上下文和帧缓冲区(如果有),并通过glViewport()设置视口。框架不设置其他状态,也不执行清除或绘图。
注意:当使用像PartialUpdateBlend
这样的部分更新行为时,上一个paintGL()调用的输出被保留,并在当前函数调用的附加绘制之后,将内容通过paintUnderGL()绘制到窗口的直接绘制内容上。
另见 initializeGL(),resizeGL(),paintUnderGL(),paintOverGL()和UpdateBehavior。
[虚保护]
void QOpenGLWindow::paintOverGL()
此虚函数在每次调用paintGL()之后被调用。
当更新模式设置为NoPartialUpdate时,此函数与paintGL()之间没有区别,在其中任何一个中执行渲染都会产生相同的结果。
与paintUnderGL()一样,此函数的渲染针对窗口的默认帧缓冲区,不受更新行为的影响。它在paintGL( )返回后调用,并在PartialUpdateBlit或四边形绘制PartialUpdateBlend之后进行。
另见 paintGL(),paintUnderGL()和UpdateBehavior。
[虚保护]
void QOpenGLWindow::paintUnderGL()
此虚函数在每次调用paintGL()之前被调用。
当更新模式设置为NoPartialUpdate
时,此函数与paintGL()之间没有区别,在其中任何一个中执行渲染都会产生相同的结果。
当使用 PartialUpdateBlend
时,差异变得显著,那里使用了额外的帧缓冲区对象。在这里,paintGL() 以此附加的帧缓冲区对象为目标,保留其内容,而 paintUnderGL() 和 paintOverGL() 则以默认帧缓冲区为目标,即直接针对窗口表面,每个显示的帧之后都会丢失其内容。
注意:当更新行为为 PartialUpdateBlit
时,请勿依赖此函数。此模式涉及在每个 paintGL() 调用之后将 paintGL() 使用的额外帧缓冲区复制到默认帧缓冲区,从而覆盖此函数在此生成的所有绘图。
另请参阅: paintGL(),paintOverGL(),以及 UpdateBehavior。
[覆盖虚保护]
void QOpenGLWindow::resizeEvent(QResizeEvent *event)
重新实现: QWindow::resizeEvent(QResizeEvent *ev).
调整大小 事件 处理程序。调用 resizeGL().
另请参阅: resizeGL().
[虚保护]
void QOpenGLWindow::resizeGL(int w, int h)
此虚函数在部件大小变化时被调用。在子类中重新实现它。新的尺寸通过 w 和 h 传递。
注意:此函数仅是一个便利函数,以便提供一个与 QOpenGLWidget 兼容的 API。与 QOpenGLWidget 不同,派生类可以自由选择覆盖 resizeEvent() 而不是此函数。
注意:避免在此函数中发布 OpenGL 命令,因为它在调用时可能没有当前上下文。如果无法避免,请调用 makeCurrent().
注意:在此处安排更新不是必需的。窗口系统会发送暴露事件,这些事件可以自动触发更新。
另请参阅:initializeGL() 和 paintGL().
QOpenGLContext *QOpenGLWindow::shareContext() const
返回:请求与此窗口的 QOpenGLContext 共享的 QOpenGLContext。
QOpenGLWindow::UpdateBehavior QOpenGLWindow::updateBehavior() const
返回此 QOpenGLWindow 的更新行为。
© 2024Qt公司 Ltd。此处包含的文档贡献是各自所有者的版权。此处提供的文档是根据自由软件基金会发布的GNU自由文档许可证1.3版本许可的。Qt及其相应标志是芬兰的和/或世界各地的Qt公司的商标。所有其他商标均为其各自所有者的财产。