opengl - QOpenGLContext 和 QGLWidget 之间的共享

标签 opengl qt5

问题的简短形式:如何使用 FBO 作为纹理在 QGLWidget 中进行绘制,而不只是获得空白的白色图像?

还有一些背景和细节...我正在使用 Qt 5.1 作为在 GPU 上进行一些图像处理的应用程序。有一个“合成器”类,它使用 QOffscreenSurface、QOpenGLContext 和 QOpenGLFramebufferObject。它向 FBO 呈现一些内容。如果应用程序在仅渲染模式下运行,结果将写入文件。以交互方式运行,它显示在我的 QGLWidget 子类“查看器”上。

如果我从 FBO 制作 QImage 并将其绘制到查看器,它就可以工作。然而,这需要从 GPU-> QImage-> 返回 GPU 作为纹理进行往返。理论上,我应该可以直接使用FBO作为纹理,这就是我想要的。

我试图在我的 QOpenGLContext 和 QGLWidget 的 QGLContext 之间共享,如下所示:

viewer = new tl::ui::glViewer(this); 合成器 = 新 tl::playback::glCompositor(1280, 720, 这个); 查看器->context()->contextHandle()->setShareContext(compositor->context);

是否可以在两种类型的上下文之间共享?这是这样做的方法吗?我是否需要做其他事情来使用合成器中的 FBO 在查看器中进行绘制?当我直接绘制 FBO 而不是 QImage 时,我只是得到纯白色,所以我显然做错了什么。

<小时/>

所以我已经解决了我的问题。我误解了 setShareContext() 的文档,其中指出它“在调用 create() 之前不会生效”,我错误地认为这意味着您必须在创建上下文后共享上下文。相反,共享必须在以下之前建立:

viewer = new tl::ui::glViewer(this);
compositor = new tl::playback::glCompositor(512, 512, viewer->context()->contextHandle(), this);

以及我的 glCompositor 的新构造函数:

offscreenSurface = new QOffscreenSurface();
QSurfaceFormat format;
format.setMajorVersion(4);
format.setMinorVersion(0);

format.setProfile(QSurfaceFormat::CompatibilityProfile);
format.setSamples(0);
offscreenSurface->setFormat(format);
offscreenSurface->create();

context = new QOpenGLContext();
context->setShareContext(srcCtx);
context->setFormat(format);
context->create();
context->makeCurrent(offscreenSurface);

QOpenGLFramebufferObjectFormat f;
f.setSamples(0);
f.setInternalTextureFormat(GL_RGBA32F);
frameBuffer = new QOpenGLFramebufferObject(w, h, f);

将在与查看者上下文共享的新上下文中创建新的 FBO。当需要绘制时,我只需绑定(bind) glBindTexture(GL_TEXTURE_2D, frameBuffer->texture());

我正在标记我得到的正确答案,即使它没有直接解决我的问题。内容非常丰富。

最佳答案

我认为您的问题与 FBO 本身无法跨上下文共享这一事实有关。但是,您可以做的是共享附加的数据存储(渲染缓冲区、纹理等)。

归根结底,FBO 只不过是一个管理读取/绘制缓冲区集合的漂亮前端,FBO 本身实际上并不是可共享的资源。事实上,尽管有这个名字,但就 API 的其余部分而言,它们甚至不是缓冲区对象;您有没有想过为什么不使用 glBufferData (...)等等? :)

Critically Important Point:

FrameBuffer Objects are not Buffer Objects; they contain no data stores; they only manage state for attachment points and provide an interface for validation and binding semantics.

This is why they cannot be shared, the same way that Vertex Array Objects cannot be shared, but their constituent Vertex Buffer Objects can.

这里的要点是:

  • 如果不存储数据,则通常不是可共享资源。

您必须寻求的解决方案将涉及使用附加到 FBO 的渲染缓冲区和纹理。如果您不做任何疯狂的事情,例如尝试同时在两个上下文中渲染,那么共享这些资源应该不会带来太多麻烦。如果您开始尝试从渲染缓冲区或纹理中读取数据,而其他上下文正在绘制其中,那么它可能会变得非常难看,所以不要这样做:P

<小时/> 由于 OpenGL 规范中使用以下语言,您可能必须先分离纹理,然后才能在其他上下文中使用它:

OpenGL 3.2 (Core Profile) - 4.4.3 纹理和帧缓冲区之间的反馈循环 - 第 230 页:

A feedback loop may exist when a texture object is used as both the source and destination of a GL operation. When a feedback loop exists, undefined behavior results. This section describes rendering feedback loops (see section 3.8.9) and texture copying feedback loops (see section 3.8.2) in more detail.

坦率地说,你的白色纹理可能是反馈循环的结果(OpenGL在3.1之前的规范版本中没有给这种情况命名,所以对“反馈循环”的正确讨论将在3.1中找到) + 仅文献)。因为这会调用未定义的行为,所以供应商之间的行为会有所不同。分离将消除未定义行为的根源,您应该可以开始了。

关于opengl - QOpenGLContext 和 QGLWidget 之间的共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19329888/

相关文章:

c++ - OpenGL - 具有多个纹理的蒙版

opengl - 如何将模型矩阵包含到 VBO 中?

c++ - 在 QT5 中我需要创建至少 20 个 QThread

c++ - 使用 CMakeLists.txt 设置 Qt5 - 找不到文件错误

c++ - Qt 样式 - 双色边框?

opengl - 什么是GPU驱动的渲染?

c - Opengl 统一变量不起作用?

c++ - qt 从 QChart 获取子项(标注)

c++ - 带有自定义模型的 QComboBox

java - 使用 LibGdx 在 Java 中出现奇怪的 CPU 使用率