2013-06-25 3 views
3

У меня есть QMainWindow с QGLWidget. Я хочу, чтобы виджет отображал «чистый» цвет по своему выбору, а не по умолчанию черный экран.Инициализировать QGLWidget с помощью glClearColor

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 ... 
} 

Это работает, и я заметил, что метод вызывается 4 раза во время запуска. Тем не менее, я хочу просто нарисовать его пустым один раз в методе paintGL(), потому что этот метод вызывается очень часто после запуска, и на самом деле существует небольшая, но значительная потеря производительности, если буферы очищаются при каждом вызове.

Так что я изменил код так:

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 ... 
} 

Теперь очистка выполняется только один раз, но я остался с черным экраном, а что с серым экраном glClearColor. Почему это? Почему QGLWidget снова нарисовал мой черный экран? И что еще более важно, как я могу убедиться, что экран мой собственный цвет по умолчанию, не перерисовывая его пустым на каждом шаге?

ответ

2

Короткий ответ:

В большинстве платформ, состояние вашего BackBuffer является неопределенной после выполнения буфера подкачки. Вы можете найти более подробную информацию here. Следовательно, вы не можете полагаться на поведение вашего буфера, оставив его перед операциями свопинга. Затем, чтобы ваша программа была кросс-платформенной, у вас нет другого выбора, чем позвонить glClear() на каждом рисунке.

На практике:

Вполне возможно, что ваша платформа/конфигурация которых гарантирует, что ваш буфер остается неизменным, или не гарантируют, но она все еще имеет место на практике. Если вы знаете, что находитесь в этих случаях после экспериментов (см. Ниже), но все же ваш экран стал черным, это значит, что каким-то образом в вашем коде вы сделали что-то «неправильное», что делает Qt явно называть glClear() со своим собственным glClearColor().

Этот код можно использовать, чтобы проверить, остается ли буфер после изменения swapBuffers(). Это на самом деле происходит в моей конфигурации: Qt 4.8 на 64bits Linux:

// -------- 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. если test == true, то я всегда называю glClearColor() с последующим glClear(), но чередуя красного цвета и зеленого цвета каждую секунду. Я действительно вижу, что цвет переключается между красным и зеленым.

  2. если test == false, то я только позвоню glClearColor() раз и навсегда в initializeGL(). Затем в paintGL я чередую между вызовами glClear() или не вызывая его. Экран остается красным, т. Е. Никогда не становится черным (или отображается единорогом), даже когда glClear() не вызывается.

Таким образом, в отношении вашей проблемы:

  1. Либо ваша конфигурация отличается от шахты (реализация SwapBuffers обеспечивается Qt и отличается в зависимости от основной оконной системы)

  2. Или ваш код сломан.

Простой способ проверить: скомпилировать мой код и посмотреть, продолжает ли он воспроизводить проблему. Если это так, то вы на случай 1., и вы ничего не можете с этим поделать (это можно считать ошибкой Qt, а скорее несогласованностью, поскольку правильное поведение не указано нигде в документации). В противном случае вы находитесь в случае 2., а затем вы должны предоставить больше своего кода, чтобы мы могли определить, в чем проблема.

+0

Хорошее предложение, но, к сожалению, неверно. Я попробовал, но это не имеет значения. – Yellow

+0

А что если вы попробуете 'setAutofillBackground (false)' в конструкторе вашего 'QGLWidget'? Если это не сработает, у вас нет другого выбора, кроме как очистить буфер на каждом 'paintGL'. Обратите внимание, что поражение производительности не должно быть проблемой, это то, что делает любая оптимизированная игра в любом случае. ;-) – Boris

+0

И это не работает, я боюсь. Я знаю, что даже в оптимизированных играх функция glClear вызывается, но у меня есть сильное моделирование, работающее в фоновом режиме, поэтому любое небольшое сокращение накладных расходов стоит того. – Yellow

Смежные вопросы