1

QGraphicsScene+を使用してコンテンツを描画するQGraphicsViewセットアップがあります。QGLWidget

また、ディスプレイスメント マップとブルーム エフェクトをシーンに追加するために、いくつかのフラグメント シェーダーも作成しました。QPainterをデバイスとしてオブジェクトを作成し、そのオブジェクトでQFramebufferObjectグラフィックス シーンのレンダリング関数を呼び出すとQPainter、シーンが FBO にレンダリングされ、それを使用して合成を行うことができます。ただし、これには、ソフトウェア レンダリングを使用し、多くのリソースを消費するという欠点があります。

残念ながら、FBO を現在のレンダー ターゲットとして設定し、FBO に描画するためにそのままにしておくとQGLWidget、FBO が空白になります (空白とはglClearColor呼び出しの色を意味します) 。

だから私の質問は基本的にQGLWidget、FBO のコンテンツを取得する方法はありますか、または後処理シェーダーを実装する他の方法はありますか?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();
}
4

0 に答える 0