问题的简短形式:如何使用我的FBO作为纹理绘制我的QGLWidget,而不仅仅是获得空白的白色图像?
并且,一些背景和细节......我正在使用Qt 5.1为在GPU上进行一些图像处理的应用程序。有一个“compositor”类,它使用QOffscreenSurface,带有QOpenGLContext和QOpenGLFramebufferObject。它给FBO带来了一些东西。如果应用程序以仅渲染模式运行,则结果将写入文件。以交互方式运行,它在我的QGLWidget子类中显示为“viewer”。
如果我从FBO制作一个QImage并将其绘制给观众,它就可以了。然而,这需要从GPU->往返的往返。 QImage->回到GPU作为纹理。理论上,我应该能够直接使用FBO作为纹理,这就是我想要的。
我试图在我的QOpenGLContext和QGLWidget的QGLContext之间分享如下:
viewer = new tl :: ui :: glViewer(this); compositor = new tl :: playback :: glCompositor(1280,720,this); 查看器而>上下文() - > contextHandle() - > setShareContext(compositor->上下文);
是否可以在两种类型的上下文之间共享?这是这样做的吗?我是否需要在合成器中使用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());
我正在标记我得到的答案,即使它没有直接解决我的问题。它非常有用。
答案 0 :(得分:2)
我认为你的问题与FBO本身不能在不同情况下共享的事实有关。但是,您可以共享附加的数据存储(渲染缓冲区,纹理等)。
事实上,FBO只是管理读取/绘制缓冲区集合的前端,FBO本身实际上并不是可共享的资源。实际上,尽管名称如此,但就API的其他部分而言,它们甚至不是Buffer Objects;你有没有想过为什么你不使用glBufferData (...)
等? :)
至关重要的一点:
FrameBuffer 对象不是缓冲区对象;它们不包含数据存储;它们只管理附着点的状态,并提供验证和绑定语义的接口。
这就是为什么它们无法共享,就像顶点数组对象无法共享一样,但它们的组成顶点缓冲区对象可以。
这里的外卖信息是:
您必须采用的解决方案将涉及使用附加到FBO的渲染缓冲区和纹理。如果你不做任何疯狂的事情,比如一次尝试并在两种情况下渲染,分享这些资源不应该带来太多麻烦。如果你开始尝试从渲染缓冲区或纹理读取而其他上下文正在绘制它时,它可能变得非常难看,所以不要这样做:P
<小时/> 由于OpenGL规范中使用了以下语言,您可能必须在将纹理用于其他上下文之前将其分离:
当纹理对象用作GL操作的源和目标时,可能存在反馈循环。当存在反馈循环时,会产生未定义的行为。本节更详细地描述了渲染反馈循环(参见第3.8.9节)和纹理复制反馈循环(参见第3.8.2节)。
直截了当地说,你的白色纹理可能是反馈循环的结果(OpenGL没有在规范版本中给出这种情况的名称。在3.1之前,所以在3.1中可以找到对“反馈循环”的正确讨论+仅限文学)。因为这会调用未定义的行为,所以供应商之间的行为会有所不同。分离将消除未定义行为的来源,你应该好好去。