【问题标题】:Render QImage with OpenGL使用 OpenGL 渲染 QImage
【发布时间】:2013-12-13 07:05:19
【问题描述】:

与我的other question 相关,我认为更核心的问题是,如何使用 OpenGL 渲染QImage

我认为代码必须看起来像这样,但我不确定我还需要什么,除了 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());

但无论哪种方式,我都看不到图像,只是一个与它大小相同的白色方块。我在这里遗漏了一些东西。

【问题讨论】:

  • 您确认imgGLGL_RGBA/GL_UNSIGNED_BYTE的格式相同吗?
  • 是的,因为我从使用GL_UNSIGNED_BYTESoOffscreenRenderer 缓冲区创建了QImage,如果它使用RGBRGBA,我可以在哪里设置。我尝试了两个版本,但都不会显示。

标签: c++ qt opengl qimage glteximage2d


【解决方案1】:

我设法从图片源中使用 OpenGL 绘制了 QImage,但不是从 SoOffscreenRenderer 中描述的 here

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 错误。

【讨论】:

  • 为什么每次画帧都要加载纹理?我认为你应该在你的 init 函数中调用它。
  • 你是对的,这在示例的结构上没有意义。我要改了。
【解决方案2】:

现在,使用 Qt 5.11,最简单的方法是使用 QOpenGLWidget 并覆盖其 paintEvent 方法。

在以下代码中,OpenGLWidget 继承自 QOpenGLWidget,display(const QImage& img) 是每当我需要更新图像时触发的插槽。

无论在两次 OpenGL 渲染之间调用多少次 display(),update() 调用都不会直接触发渲染,它只是将小部件标记为脏,以便在下一个循环中重绘。

这个方法其实很快,我用它来以 240fps 显示相机帧(虽然不是所有帧都显示在屏幕上)。

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

void OpenGLWidget::paintEvent(QPaintEvent*)
{
  QPainter painter(this);
  painter.drawImage(this->rect(),image);
}

【讨论】:

  • 谢谢。如果我有一个视频墙,比如说 3 x 3,每个视频墙摄像头图像支架是否应该是 QOpenGLWidget(现在它们是带有 qlabels 的 qwidgets 并且工作速度非常慢)。或者,墙本身应该是 QOpenGLWidget 吗?或者他们都必须是?我应该让主窗口也成为 QOpenGlWidget 吗?我在哪里可以阅读这些主题(QOpenglWidget 和 QWidget 之间的孩子和父母)?最好的祝福!垫子。
  • 嘿,我不认为你想让我看电影)
  • 视频墙与 QOpenGLWidget 没有任何关系。您应该设置设备的方式(所有部分只有一个 OpenGL,或每个部分只有一个 openGL 窗口)取决于很多事情(首先是您的操作系统和显卡)。关于您的最后一个问题,您可以在此处找到 Qt5 文档:doc.qt.io/qt-5.11。值得一读
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-11
  • 2023-03-23
  • 1970-01-01
  • 2019-10-12
  • 2014-04-06
相关资源
最近更新 更多