Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将QGLWdiget内容绘制到FBO_C++_Qt_Opengl_Fbo - Fatal编程技术网

C++ 将QGLWdiget内容绘制到FBO

C++ 将QGLWdiget内容绘制到FBO,c++,qt,opengl,fbo,C++,Qt,Opengl,Fbo,我有一个QGraphicscene+QGraphicsView设置,它使用QGLWidget来绘制内容 我还制作了一些片段着色器,以向场景添加置换贴图和bloom效果。如果我使用QFramebufferObject作为设备创建QPaint对象,并在QPaint对象上调用图形场景的渲染功能,场景将渲染到FBO,然后我可以使用它进行合成。但是,它的缺点是使用软件渲染,并且会占用大量资源 不幸的是,当我尝试将一个FBO设置为当前渲染目标,并将QGLWidget留在FBO上绘制时,FBO显示为空白,我所

我有一个QGraphicscene+QGraphicsView设置,它使用QGLWidget来绘制内容

我还制作了一些片段着色器,以向场景添加置换贴图和bloom效果。如果我使用QFramebufferObject作为设备创建QPaint对象,并在QPaint对象上调用图形场景的渲染功能,场景将渲染到FBO,然后我可以使用它进行合成。但是,它的缺点是使用软件渲染,并且会占用大量资源

不幸的是,当我尝试将一个FBO设置为当前渲染目标,并将QGLWidget留在FBO上绘制时,FBO显示为空白,我所说的空白是指glClearColor调用的颜色

所以我的问题是,有没有一种方法可以在FBO上获取QGLWidget的内容,或者有没有其他方法可以在QGLWidget中实现后期处理着色器

以下是我当前代码的相关部分

void MyWindow::SwitchRenderContext(RenderType type)
{
    m_renderType = type;
    m_renderArea->SetRenderType(type);
    switch(type)
    {
    case RenderType_Software:
        m_view.setViewport(NULL);
        layout()->removeWidget(&m_view);
        layout()->addWidget(m_renderArea);
        m_view.m_renderWidget = NULL;
        break;
    case RenderType_OpenGL:
        m_view.setViewport(m_renderArea);
        m_view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        layout()->addWidget(m_renderArea);
        m_view.m_renderWidget = m_renderArea;
        break;
    }
}

void MyGlWidget::initializeGL()
{
    m_initialized = true;
    if(m_dispFbo == NULL)
        m_dispFbo = new QGLFramebufferObject(width(), height());
    if(m_bufFbo == NULL)
        m_bufFbo = new QGLFramebufferObject(width(), height());
    if(m_fbo == NULL)
        m_fbo = new QGLFramebufferObject(width(), height());

    static const float vertex[] = {
        -1.0f,  1.0f, 0.0f, 1.0f,
        1.0f,  1.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 0.0f, 1.0f,
    };

    //initialize vbo
    if(!m_vbo.isCreated())
    {
        m_vboEnabled = m_vbo.create();
        if(m_vboEnabled)
        {
            m_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
            m_vbo.bind();
            m_vbo.allocate(vertex, sizeof(vertex) );
            m_vbo.release();
        }
        glEnable(GL_TEXTURE_2D);
    }
    glViewport(0, 0, width(), height());
    m_shadersEnabled = initializeShaders();
}

void MyGlWidget::SetRenderType(RenderType type)
{
    m_renderType = type;
}

void MyGlWidget::DoHardwarePaint()
{
    m_fbo->release();
    QPainter dispPainter(m_dispFbo);
    m_dispScene->RenderScene(&dispPainter);
    dispPainter.end();

    DrawShaders();

    m_fbo->bind();
}

void MyGlWidget::DoSoftwarePaint()
{
    if(!m_shadersEnabled || !m_vboEnabled)
    {
        QPainter painter(this);
        m_scene->render(&painter);
        return;
    }

    QPainter dispPainter(m_dispFbo);
    m_dispScene->RenderScene(&dispPainter);
    dispPainter.end();

    QPainter painter(m_fbo);
    m_scene->render(&painter);
    painter.end();

    DrawShaders();
    update();

}

void MyGlWidget::DrawShaders()
{
    m_vbo.bind();
    m_bufFbo->bind();
    glDisable(GL_DEPTH_TEST);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_dispFbo->texture());

    m_displaceShader.bind();
    m_displaceShader.enableAttributeArray("in_verts");
    m_displaceShader.setAttributeBuffer( "in_verts", GL_FLOAT, 0, 4);
    m_displaceShader.setUniformValue("inCol", 0);
    m_displaceShader.setUniformValue("inDisplace", 1);
    glDrawArrays(GL_TRIANGLES, 0, m_vbo.size());

    m_bufFbo->release();

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_bufFbo->texture());

    m_bloomShader.bind();
    m_bloomShader.enableAttributeArray("in_verts");
    m_bloomShader.setAttributeBuffer( "in_verts", GL_FLOAT, 0, 4);
    m_bloomShader.setUniformValue("inCol", 0);
    m_bloomShader.setUniformValueArray("offsets", offsets, 8, 2);
    glDrawArrays(GL_TRIANGLES, 0, m_vbo.size());

    m_bloomShader.disableAttributeArray("in_verts");
    m_bloomShader.release();

    m_vbo.release();
    glEnable(GL_DEPTH_TEST);
}

void MyGlWidget::paintGL()
{
    if(!m_vboEnabled && m_renderType == RenderType_OpenGL)
        return;

    if(m_renderType == RenderType_Software)
    {
        DoSoftwarePaint();
        return;
    }

    DoHardwarePaint();
}

我不确定这是否与QGLWidget本身有关。如果它实际上与使用QGLWidget有关,那么我能想到的唯一一件事就是Qt切换绑定的方式。当绘制一个GL上下文时,渲染上下文一次只能绑定到一个线程,因此如果QGLWidget定义了自己的上下文,麻烦就会接踵而至。解决这个问题的基本方法是实现上下文共享。您能详细介绍一下QGLWidget设置吗?感谢您的评论,这确实是因为QPaint为渲染场景而创建的视图在内部重置了状态,以便在绘制之前绑定当前活动显示的默认帧缓冲区,而不是绕过此问题,我发现了为什么QPainter在绘制QGLFramebufferObject时使用软件渲染,显然,如果在创建对象时没有将CombinedDephsTencil作为附件传递,就会发生这种情况。它的工作正如预期的那样,现在不再占用CPU了,谢谢你的提示。