OpenGL + QT: визуализировать в текстуру и отображать ее обратно

После некоторых проблем мне удалось правильно отобразить текстуру внутри объекта кадрового буфера в приложении Qt 4.8: я могу открыть контекст OpenGL с помощью QGLWidget, отобразить в FBO и использовать его в качестве текстуры.

Теперь мне нужно отобразить текстуру, отображаемую в QPixmap, и показать ее в каком-то другом виджете в графическом интерфейсе. Но.. ничего не показано.

Это некоторые фрагменты кода:

// generate texture, FBO, RBO in the initializeGL
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

// now in paintGL
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
// .... render into texture code ....
if(showTextureInWidget==false) {
    showTextureInWidget = true;
    char *pixels;
    pixels = new  char[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4];
    glReadPixels(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
    QPixmap qp = QPixmap(pixels);
    QLabel *l = new QLabel();
    // /* TEST */ l->setText(QString::fromStdString("dudee"));
    l->setPixmap(qp);
    QWidget *d = new QWidget;
    l->setParent(d);
    d->show();
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind
// now draw the scene with the rendered texture

Я вижу, что виджет открыт, но... внутри него ничего нет. Если я раскомментирую тестовую строку.. Я вижу строку чувака, поэтому я знаю, что есть qlabel, но.. нет изображения из QPixmap.

Я знаю, что исходные данные представляют собой «unsigned char», и я использую «char» и пробовал с некоторыми другими параметрами цвета («GL_RGBA», «GL_RGB» и т. д.), но я не думаю, что это главное. .. дело в том, что я ничего не вижу..

Любой совет? Если мне нужно опубликовать больше кода, я сделаю это!

Редактировать:

Я не опубликовал весь код, но хочу прояснить, что текстура правильно отображается как текстура внутри куба. Я просто не могу вставить его обратно в процессор из gpu

Редактировать 2:

Благодаря ответу peppe я обнаружил проблему: мне нужен объект Qt, который принимает в качестве конструктора некоторые необработанные данные пикселей. Вот полный фрагмент:

    uchar *pixels;
    pixels = new uchar[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4];
    for(int i=0; i < (TEXTURE_WIDTH * TEXTURE_HEIGHT * 4) ; i++ ) {
        pixels[i] = 0;
    }

    glBindFramebuffer(GL_FRAMEBUFFER, fboId);
    glReadPixels( 0,0,  TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    qi = QImage(pixels, TEXTURE_WIDTH, TEXTURE_HEIGHT, QImage::Format_ARGB32);
    qi = qi.rgbSwapped();

    QLabel *l = new QLabel();
    l->setPixmap(QPixmap::fromImage(qi));
    QWidget *d = new QWidget;
    l->setParent(d);
    d->show();

person nkint    schedule 27.06.2013    source источник
comment
Ваш код кажется явно неполным — например, вы не настраиваете цветовое вложение для своего FBO. Кроме того, при использовании FBO всегда проверяйте их статус полноты с помощью glCheckFramebufferStatus -- любая ошибка GL_FRAMEBUFFER_COMPLETE указывает на то, что ваш FBO непригоден для использования.   -  person peppe    schedule 27.06.2013
comment
Да, это в коде, я просто не копировал. конечно, я делаю проверки с glCheckFramebufferStatus. Факт, который я хотел бы уточнить, заключается в том, что визуализированная текстура (как текстура куба) правильно визуализируется.   -  person nkint    schedule 27.06.2013


Ответы (1)


Учитывая, что это не весь ваш код и, как вы говорите, текстура заполнена правильно, то здесь происходит небольшая ошибка:

glReadPixels(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
QPixmap qp = QPixmap(pixels);

QPixmap(const char *) ctor хочет изображение XPM, а не необработанные пиксели. Вам нужно использовать один из ctors QImage для создания действительного QImage. (Вы также можете передать право собственности на QImage, решив тот факт, что вы в настоящее время пропускаете pixels...)

Как только вы это сделаете, вы поймете, что

  1. изображение перевернуто по вертикали, так как OpenGL имеет начало в левом нижнем углу, увеличиваясь вверх/вправо, в то время как Qt предполагает начало в левом верхнем углу, увеличиваясь вниз/вправо;

  2. каналы могут быть перепутаны местами, т. е. OpenGL возвращает данные с неправильным порядком байтов. Я не помню в этом случае, может ли помочь использование glPixelStorei(GL_PACK_SWAP_BYTES) или GL_UNSIGNED_INT_8_8_8_8 в качестве типа, в конечном итоге вам нужно прибегнуть к циклу на стороне процессора, чтобы исправить ваши данные пикселей :)

person peppe    schedule 27.06.2013