Question

I have a QMainWindow with a QGLWidget in it. I want the widget to display a 'clear' colour of my own choice, instead of the default black screen.

void MyQGLWidget::initializeGL(void) {
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
}

void MyQGLWidget::paintGL(void) {       
     qDebug("Painting grey-ness");
     glClear(GL_COLOR_BUFFER_BIT);

     // ... Do more stuff, but only after a certain event has happened ...
}

This works, and I noticed that the method is called 4 times during the start-up. However, I only want to paint it blank once in the paintGL() method, because this method is being called very often after the start-up, and there actually is small but significant performance loss if the buffers are cleared at every call.

So I changed the code to this:

void MyQGLWidget::paintGL(void) {
    static bool screenOnBlank = false;
    if (!screenOnBlank) {
         qDebug("Painting grey-ness");
         glClear(GL_COLOR_BUFFER_BIT);
         screenOnBlank = true;
     }

    // ... Do more stuff, but only after a certain event has happened ...
}

Now the clearing is only done once, but I am left with a black screen, rather that with the grey screen of glClearColor. Why is this? Why does QGLWidget paint my screen black again? And more importantly, how can I make sure the screen is my own default colour, without repainting it blank at every time step?

Was it helpful?

Solution

Short answer:

In most platforms, the state of your backbuffer is undefined after performing a buffer swap. You can find more details here. Hence, you cannot rely on the behaviour that your buffer remains as you left it before the swap operations. Then, to ensure your program is cross-platform, you have no other choice than calling glClear() at each drawing.

In practice:

It is possible that your platform/configuration do guarantee that your buffer is unchanged, or don't guarantee it but it is still the case in practice. If you know you are in those cases after experimenting (see below), but still have your screen turned black, it means that somehow in your code, you did something "wrong" that makes Qt explicitly call glClear() with its own glClearColor().

You can use this code to see if the buffer remains unchanged after swapBuffers(). It is actually the case in my configuration: Qt 4.8 on Linux 64bits:

// -------- main.cpp --------

#include <QApplication>
#include "GLWidget.h"

int main(int argc, char ** argv)
{
    QApplication app(argc, argv);
    GLWidget * w = new GLWidget();
    w->show();
    return app.exec();
}


// -------- GLWidget.h --------

#include <QGLWidget>
#include <QTimer>


class GLWidget: public QGLWidget
{
    Q_OBJECT

public:
    GLWidget() : i(0), N(60)
    {
        timer.setInterval(16);
        connect(&timer, SIGNAL(timeout()), 
              this, SLOT(animationLoop()));
        timer.start();
    }


protected:
     void initializeGL()
     {
         glClearColor(1.0, 0.0, 0.0, 1.0);
     }

     void resizeGL(int w, int h)
     {
         glViewport(0, 0, (GLint)w, (GLint)h);
     }

     void paintGL()
     {
         bool test = false;
         if(i<N)
         {
             if(test)
                 glClearColor(1.0, 0.0, 0.0, 1.0);
             glClear(GL_COLOR_BUFFER_BIT);
         }
         else
         {
             if(test)
             {
                 glClearColor(0.0, 1.0, 0.0, 1.0);
                 glClear(GL_COLOR_BUFFER_BIT);
             }
         }
     }

private slots:
    void animationLoop() 
    {
         i++;
         if(i>2*N) i=0;
         updateGL();
    }

private:
    int i, N;
    QTimer timer;
};
  1. if test == true, then I always call glClearColor() followed by glClear(), but alternating between a red color and a green color every second. I indeed see the color switching back and forth between red and green.

  2. if test == false, then I only call glClearColor() once and for all in initializeGL(). Then in paintGL, I alternate between calling glClear() or not calling it. The screen stays red, i.e. never turns black (or display a unicorn) even when glClear() is not called.

Hence, regarding your problem:

  1. Either your configuration is different than mine (the implementation of swapBuffers is provided by Qt and differs according to the underlying window system)

  2. Or your code is broken.

Simple way to check: compile my code, and see if it still reproduces the issue. If it does, then you are in case 1., and there is nothing you can do about it (can be considered a bug of Qt, of rather an inconsistency, since the correct behaviour is not specified anywhere in the documentation). Otherwise, you are in case 2., and then you should provide more of your code so we could determine where is the issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top