问题的简短形式:如何使用我的FBO作为纹理在我的QGLWidget中绘制,而不仅仅是获得空白的白色图像?
而且,一些背景和细节... 我正在使用Qt 5.1作为在GPU上进行一些图像处理的应用程序。 有一个"compositor"类,它使用QOffscreenSurface,QOpenGLContext和QOpenGLFramebufferObject。它向FBO呈现一些东西。如果应用在仅呈现模式下运行,则结果将写入文件。以交互方式运行,它显示在我的QGLWidget"查看器"子类上。
如果我从FBO制作一个QImage并将其绘制给观众,它就会起作用。但是,这需要从 GPU> QImage-> 回到 GPU 作为纹理。理论上,我应该可以直接将FBO用作纹理,这就是我想要的。
我试图在我的QOpenGLContext和QGLWidget的QGLContext之间共享,如下所示:
viewer = new tl::ui::glViewer(this);compositor = new tl::p layback::glCompositor(1280, 720, this);viewer->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。 到了画的时候,我只是绑定glBindTexture(GL_TEXTURE_2D,frameBuffer->texture());
我正在标记我得到的正确答案,即使它没有直接解决我的问题。 这是非常翔实的。
我相信你的问题与FBO本身不能跨上下文共享的事实有关。但是,您可以做的是共享附加的数据存储(渲染缓冲区、纹理等)。
它实际上归结为这样一个事实,即FBO只不过是一个管理读/画缓冲区集合的漂亮前端,FBO本身实际上并不是一个可共享的资源。事实上,尽管名称如此,但就 API 的其余部分而言,它们甚至不是缓冲区对象;你有没有想过为什么你不使用glBufferData (...)
等?:)
至关重要的一点:
FrameBuffer 对象不是缓冲区对象;它们不包含数据存储;它们仅管理连接点的状态,并提供用于验证和绑定语义的接口。
这就是为什么它们不能被共享,就像顶点数组对象不能共享一样,但它们的组成顶点缓冲区对象可以共享。
这里的要点是:
- 如果它不存储数据,则通常不是可共享的资源。
您必须追求的解决方案将涉及使用附加到FBO的渲染缓冲区和纹理。只要您不做任何疯狂的事情,例如同时在两个上下文中尝试渲染,共享这些资源就不会带来太多麻烦。如果您在其他上下文正在绘制时开始尝试从渲染缓冲区或纹理中读取,它可能会变得非常丑陋,因此不要这样做:P
由于 OpenGL 规范中的以下语言,您可能必须先分离纹理,然后再在其他上下文中使用它:
OpenGL 3.2 (核心配置文件) - 4.4.3 纹理和帧缓冲之间的反馈循环 - 第230页:
当纹理对象同时用作 GL 操作的源和目标时,可能存在反馈循环。当反馈循环存在时,会产生未定义的行为。本节更详细地介绍渲染反馈循环(参见第 3.8.9 节)和纹理复制反馈循环(参见第 3.8.2 节)。
坦率地说,你的白色纹理可能是反馈循环的结果(OpenGL 在 3.1 之前的规范版本中没有给这种情况命名,所以关于"反馈循环"的正确讨论只能在 3.1+ 文献中找到)。因为这会调用未定义的行为,所以它在供应商之间的行为会有所不同。分离将消除未定义行为的来源,您应该很高兴。