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:
- There is some kind of uninitialized buffer involved. Do you have any idea which one?
- 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 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.") ); } }