Qt5 中屏幕和屏幕外渲染与 QOpenGL\* 类之间的交互
Posted
技术标签:
【中文标题】Qt5 中屏幕和屏幕外渲染与 QOpenGL\\* 类之间的交互【英文标题】:Interactions between Onscreen and Offscreen rendering in Qt5 with QOpenGL\* classesQt5 中屏幕和屏幕外渲染与 QOpenGL\* 类之间的交互 【发布时间】:2016-08-29 08:32:26 【问题描述】:目标:
通过Qt5 OpenGL框架进行一些onscreen和offscreen渲染,这样资源可以很容易地在两个渲染部分之间共享。具体来说,
渲染工作通过offscreen部分完成(framebuffer可能比显示屏幕大); 屏幕外渲染的结果可以在不同的设置下显示在多个屏幕上部分(例如QOpenGLWidget
s),例如不同尺寸,为简单起见;
离屏渲染的结果也可以从 GPU 中提取并保存到QImage
或cv::Mat
对象中;
上述任务可以异步执行(进行第二次离屏渲染,同时显示或提取第一个离屏结果)。
目前的解决方案:
由于我不知道如何在两个部分之间共享资源,因此在我当前的解决方案中,实际的渲染工作在两个部分中都是冗余完成的:
屏幕上部分: 一个QMainWindow
包含多个QOpenGLWidget
(QOpenGLWidget
的子类)对象;
屏幕外部分:
包含QOffscreenSurface
、QOpenGLContext
和QOpenGLFramebufferObject
指针成员的自定义类以及用于调用OpenGL 函数的QOpenGLFunctions
指针执行实际渲染工作,与this link 非常相似。李>
实际渲染器:
如上所述,实际的渲染工作被提取到一个单独的类中,并且两个部分(onscreen和offscreen)都有自己的句柄。
问题:
有两个QOpenGLContext
s:
QWindow
的QOffscreenSurface
不允许存在于gui线程之外;
在主 (GUI) 线程中执行此操作时,它说 QOpenGLContext
无效。
所以我的问题是:
我是否应该在同一个 GUI 线程中执行 offscreen 和 onscreen 工作? 屏幕外和屏幕部分之间交流和共享资源的最佳方式是什么?非常感谢一个简短的实际代码示例做一个简单的渲染工作(例如,通过着色语言绘制一个三角形)。
【问题讨论】:
【参考方案1】:假设QOpenGLContext *main_ctx
是QOpenGLWidget
创建的用于实际渲染的上下文,您可以在任何线程中创建另一个上下文ctx
并使其与第一个线程共享纹理和缓冲区:
ctx = std::make_unique<QOpenGLContext>();
ctx->setFormat(main_ctx->format());
ctx->setShareContext(main_ctx);
ctx->create();
我认为QOffscreenSurface
不一定是基于QWindow
的。
offscreen_surface = std::make_unique<QOffscreenSurface>();
offscreen_surface->setFormat(ctx->format());
offscreen_surface->create();
ctx->makeCurrent(offscreen_surface);
然后创建一个QOpenGLFramebufferObject
并从第二个上下文(第二个线程)渲染到它。
然后在主要上下文中使用它的纹理:glBindTexture(GL_TEXTURE_2D, fbo->texture());
。这样做时可能需要一些同步。
【讨论】:
感谢您的帮助。多个 offscreen 部分(在多个线程中),其渲染结果会按照某些规则依次显示在同一个 onscreen 部分中怎么办?他们的ctx
s 是否应该共享相同的main_ctx
?如果随后使用多个fbo
s(来自多个屏幕外部分),它们会相互重叠吗?或者多个fbo->texture()
s 会返回相同的值吗?如果有,如何避免?我对fbo
的机制和纹理不是很熟悉。
这不像“共享同一个 main_ctx”,因为所有共享上下文具有平等的权利:它们共享共享纹理、着色器和其他 OpenGL 资源。关于 FBO:Qt 似乎为每个 FBO 创建了一个单独的纹理来使用。
再次感谢您的帮助!根据您的建议,我尝试将纹理 ID unit
从 FBO(offscreen 部分)转移到 QOpenGLTexture
(onscreen 部分),但没有显示所需的纹理。我认为原因可能是不熟悉将QOpenGLTexture
与FBO 一起使用。 Qt5.7的文档说可以渲染TO纹理,也可以渲染WITH纹理。有没有关于这两种用法的简单例子。 (这可能是另一个问题,我应该发布一个新帖子吗?)
提出另一个问题,所以会有一个空间来显示带有QOpenGLFramebufferObject
的代码不起作用。如果该代码是一个足够独立的示例,那么有人可能会修复该代码。
一个新问题 (this link) 已发布。非常感谢!以上是关于Qt5 中屏幕和屏幕外渲染与 QOpenGL\* 类之间的交互的主要内容,如果未能解决你的问题,请参考以下文章
使用 Docker 使用 QOffscreenSurface 进行屏幕外渲染
是否可以在屏幕外渲染 QWebEnginePage/QWebEngineView?