Визуализировать QImage с помощью OpenGL

Что касается моего другого вопроса, я думаю, что более важным будет вопрос о том, как вы визуализируете QImage с OpenGL?

Я думаю, что код должен выглядеть примерно так, но я не уверен, что еще мне нужно, кроме, может быть, convertToGLFormat(img).

glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glGenTextures(1, &offscreenBufferTexture);
glBindTexture(GL_TEXTURE_2D, offscreenBufferTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgGL.width(),
         imgGL.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
         imgGL.bits());

glBegin(GL_QUADS);
  glTexCoord2d(0,0); glVertex2d(0, 0);
  glTexCoord2d(1,0); glVertex2d(windowSize.width(), 0);
  glTexCoord2d(1,1); glVertex2d(windowSize.width(), windowSize.height());
  glTexCoord2d(0,1); glVertex2d(0, windowSize.height());
glEnd();
glDisable(GL_TEXTURE_2D);

Кроме того, я подумал, что быстро и грязно, вы могли бы использовать glDrawPixels() (хотя вы не должны), например

glDrawPixels(imgGL.width(), imgGL.height(), GL_RGBA,
         GL_UNSIGNED_BYTE, imgGL.bits());

Но в любом случае я не вижу изображения, просто белый квадрат размером с него. Я что-то здесь упускаю.


person Dreiven    schedule 27.11.2013    source источник
comment
Вы подтвердили, что imgGL имеет тот же формат, что и GL_RGBA/GL_UNSIGNED_BYTE?   -  person cmannett85    schedule 28.11.2013
comment
Да, потому что я создаю QImage из буфера SoOffscreenRenderer, который использует GL_UNSIGNED_BYTE, и где я могу установить, использует ли он RGB или RGBA. Я пробовал обе версии, но он не отображается ни в одном из них.   -  person Dreiven    schedule 28.11.2013


Ответы (2)


Мне удалось нарисовать QImage с помощью OpenGL из источника изображения, но не из SoOffscreenRenderer, как описано здесь.

void init(){
    loadTexture2("kitten.png", backgroundimage);
}

QImage loadTexture2(char *filename, GLuint &textureID){
    glEnable(GL_TEXTURE_2D); // Enable texturing

    glGenTextures(1, &textureID); // Obtain an id for the texture
    glBindTexture(GL_TEXTURE_2D, textureID); // Set as the current texture

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    QImage im(filename);
    QImage tex = QGLWidget::convertToGLFormat(im);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

    glDisable(GL_TEXTURE_2D);

    return tex;
}

void renderSceneGL2(){
    glClearColor(0.4f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, backgroundimage);

    glBegin(GL_QUADS);
        glTexCoord2f(0,0); glVertex3f(-1, -1, -1);
        glTexCoord2f(1,0); glVertex3f(1, -1, -1);
        glTexCoord2f(1,1); glVertex3f(1, 1, -1);
        glTexCoord2f(0,1); glVertex3f(-1, 1, -1);

    glEnd();

    glDisable(GL_TEXTURE_2D);
}

Также QGLWidget::convertToGLFormat время от времени выдает случайные Access violation ошибки.

person Dreiven    schedule 06.12.2013
comment
почему вы загружаете текстуру каждый раз, когда рисуете кадр? я думаю, что вы должны вызвать его в своей функции инициализации. - person Nazar554; 06.12.2013
comment
Ну, вы правы, это не имеет смысла в том, как структурирован пример. Я собираюсь изменить это. - person Dreiven; 06.12.2013

В настоящее время, с Qt 5.11, самый простой способ — использовать QOpenGLWidget и переопределить его метод paintEvent.

В следующем коде OpenGLWidget наследуется от QOpenGLWidget, а display(const QImage& img) — это слот, запускаемый всякий раз, когда мне нужно обновить изображение.

Независимо от того, сколько раз вызывается display() между двумя рендерингами OpenGL, вызов update() не запускает рендеринг напрямую, он просто помечает виджет как грязный для перерисовки в следующем цикле.

Этот метод на самом деле довольно быстрый, я использую его для отображения кадров камеры со скоростью 240 кадров в секунду (хотя не все кадры отображаются на экране).

void OpenGLWidget::display(const QImage& img)
{
  image = img;
  this->update();
}

void OpenGLWidget::paintEvent(QPaintEvent*)
{
  QPainter painter(this);
  painter.drawImage(this->rect(),image);
}
person antoine    schedule 03.08.2018
comment
Спасибо. Если у меня есть видеостена, скажем, 3 на 3, каждый держатель изображения камеры видеостены должен быть QOpenGLWidget (теперь это qwidgets с qlabels и работают очень медленно). Или сама стена должна быть QOpenGLWidget? или они оба должны быть? Должен ли я сделать главное окно также QOpenGlWidget? Где я могу прочитать об этих темах (дети и родители между QOpenglWidget и QWidget)? С наилучшими пожеланиями! Мат. - person hagor; 10.09.2018
comment
хех, я не думаю, что ты хотел, чтобы я смотрел мовидиус ) - person hagor; 13.09.2018
comment
видеостена никак не связана с QOpenGLWidget. То, как вы должны настроить свое устройство (только с одним OpenGL для всех частей или с одним окном openGL для каждой части), зависит от многих вещей (в первую очередь от вашей ОС и графической карты). Что касается вашего последнего вопроса, вы найдете документацию Qt5 здесь: doc.qt.io/qt-5.11< /а>. Это стоит прочитать - person antoine; 14.09.2018