Bare minimal QOpenGLFramebufferObject render to texture: Rendered triangle contains "noise"



  • Hello,
    I am trying to make a minimal example that renders the famous red triangle to a texture. I tried this using the following code:

    void GLWidget::initializeGL()
    {
        initializeOpenGLFunctions();
        glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
        m_vao = new QOpenGLVertexArrayObject(this);
        m_vao->create();
        m_vao->bind();
        static const GLfloat g_vertex_buffer_data[] = {
           -1.0f, -1.0f, 0.0f,
           1.0f, -1.0f, 0.0f,
           0.0f,  1.0f, 0.0f,
        };
        m_vertexBuffer.create();
        m_vertexBuffer.bind();
        m_vertexBuffer.allocate(g_vertex_buffer_data, sizeof(g_vertex_buffer_data));
        m_program = new QOpenGLShaderProgram(this);
        m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vertexshader.glsl");
        m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fragmentshader.glsl");
        m_program->link();
        m_program->enableAttributeArray(0);
        m_program->setAttributeBuffer(0, GL_FLOAT,0,3,0);
        m_framebuffer = new QOpenGLFramebufferObject(QSize(512,512), GL_TEXTURE_2D);
        m_filename = "C:/Users/Axel/Desktop/phased-array/trunk/testcases/build-rendertotexture-Desktop_Qt_5_8_0_MinGW_32bit2-Debug/test.png";
        glDisable(GL_DEPTH_TEST);
    }
    
    void GLWidget::paintGL()
    {
        m_framebuffer->bind(); // <= uncomment this one to draw on screen, which works perfectly
        glViewport(0,0,512,512);
    
        m_vao->bind();
        m_program->bind();
    
        glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
        glFinish();
    
        QImage fbo_img(m_framebuffer->toImage());
    
        fbo_img.save(m_filename);
    }
    

    When I uncomment the first two lines of my drawing routine, e.g. m_framebuffer->bind(); and glViewport(0,0,512,512); I get my red triangle as expected on the screen. When I render to the FBO and look into the resulting file, only about maybe half of the pixels are red, the others stay black. The black and red pixel follow a noise-like pattern and on each drawing calls, different pixels belonging to the triangle are red or black.

    I see two possible explainations:

    1. There is some kind of uninitialized buffer involved. Do you have any idea which one?
    2. The graphics card is still busy drawing all the fragments while I save the image. I tried fixing this by calling glFinish, but was not successfull.

    Do you have any idea what might went wrong in my case?

    Best regards

    Axel



  • Just a shot in the dark, in case the problem is number 2) maybe you should try to save to the file outside the paintGL()



  • Just to be clear, are you using QGLWidget?

    I might be wrong, but I have a feeling that the FBO isn't fully updated at the time of m_framebuffer->toImage().
    If that's the case, you need to find a way to execute that at a point where the rendering (paintGL) is done. Maybe updateGL()?

    Ps. I just saw johngod pointing in the same direction. Maybe this answer give some more value. Ds.



  • Any way, if all you want to do is create a image file from the window and if you using QOpenGLWidget I just remember I have done it before, check the following snipet that you can adatp to your needs:

    void XXXXX::SaveImageAs()
    {
        QString filename;
        filename = QFileDialog::getSaveFileName( this,
                                                tr("Save File"),
                                                getenv( "HOME" ), tr(" Image (*.png)") );
                                                //getenv( "HOME" ), fileformat );
    
        if( !filename.endsWith( ".png" ) )
        {
            filename.append( ".png" );
        }
    
        QPixmap pixmap( size() );
        render( &pixmap );
        QImage image = grabFramebuffer();
        QImageWriter imageWriter( filename, "png" );
    
        //imageWriter.setQuality(100);
    
        if( imageWriter.canWrite() )
        {
            imageWriter.write(image);
        }
        else
        {
            QMessageBox::warning( this, tr("Save Image"), tr("Error saving image.") );
        }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.