1

经过一些麻烦后,我设法在 Qt 4.8 应用程序中正确渲染到帧缓冲区对象内的纹理:我可以使用 QGLWidget 打开 OpenGL 上下文,渲染到 FBO,并将其用作纹理。

现在我需要显示在 QPixmap 中渲染的纹理,并将其显示在 gui 的其他一些小部件中。但是..什么都没有显示。

这些是一些代码:

// 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

我看到小部件打开了,但是......里面什么都没有。如果我取消测试线..我看到“dudee”字符串,所以我知道有一个 qlabel 但是..没有来自 QPixmap 的图像。

我知道原始数据是“unsigned char”,我正在使用“char”,并且尝试了一些不同的颜色参数(“GL_RGBA”、“GL_RGB”等),但我认为这不是重点。 ..关键是我什么都没看到..

有什么建议吗?如果我必须发布更多代码,我会这样做!

编辑:

我没有发布所有代码,但我想明确的是纹理被正确渲染为立方体内的纹理。我只是无法将它从 gpu 放回 cpu

编辑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();
4

1 回答 1

2

鉴于这不是您的全部代码,并且 - 正如您所说 - 纹理已正确填充,那么这里发生了一个小错误:

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

QPixmap(const char *)ctor 需要 XPM 图像,而不是原始像素。您需要使用其中一个 QImage ctors 来创建有效的 QImage。(您还可以将所有权传递给 QImage,解决您当前正在泄漏的事实pixels......)

一旦你这样做了,你就会发现

  1. 图像垂直翻转,因为 OpenGL 的原点位于左下角,向上/向右增长,而 Qt 假定原点在左上角,向下/向右增长;

  2. 通道可能会被交换——即 OpenGL 正在以错误的字节顺序返回数据。我不记得在这种情况下是否使用glPixelStorei(GL_PACK_SWAP_BYTES)orGL_UNSIGNED_INT_8_8_8_8作为类型可能会有所帮助,最终您需要求助于 CPU 端循环来修复您的像素数据:)

于 2013-06-27T16:27:09.523 回答