OpenGL:读取颜色缓冲区

时间:2018-12-30 17:26:48

标签: c++ opengl graphics textures framebuffer

我将4个颜色缓冲区附加到帧缓冲区并在每个缓冲区中进行渲染。每个颜色缓冲区都有窗口的大小。我正在尝试使用鼠标指针的坐标读取这些颜色缓冲区之一的像素的颜色。

鼠标移动事件处理程序

void mouseMoveEvent(QMouseEvent *event)
{
    int x = event->pos().x();
    int y = event->pos().y();

    makeCurrent();
    glBindFramebuffer(GL_READ_FRAMEBUFFER, FBOIndex::GEOMETRY);
    {
        // I save the values I'm interested in in the attachment GL_COLOR_ATTACHMENT3
        // but I always get 0 from any other attachment I try
        glReadBuffer(GL_COLOR_ATTACHMENT3);

        QVector<GLubyte> pixel(3);
        glReadPixels(x, geometry().height() - y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &(pixel[0]));

        QString PixelColor = QColor(pixel[0], pixel[1], pixel[2]).name();    
        qDebug() << PixelColor; // => always 0
    }
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
    doneCurrent();
}

但是对于每个颜色缓冲区,我总是读取值0。

颜色缓冲区在渲染阶段正确写入,我通过显示它们所附着的纹理来测试了每个颜色缓冲区。我还测试了鼠标指针选择的默认帧缓冲区的像素读数,它可以正常工作。

我在哪里错了? 谢谢!

编辑

看似奇怪的是,如果我使用“专用”帧缓冲区,则可以正确读取存储在纹理中的值。

void mouseMoveEvent(QMouseEvent *event)
{
    int x = event->pos().x();
    int y = event->pos().y();

    GLuint fbo;

    makeCurrent();
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    {
        GLuint texture = textures[TextureIndex::COLOUR];
        glBindTexture(GL_TEXTURE_2D, texture);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

        QVector<GLubyte> pixel(3);
        glReadPixels(x, geometry().height() - y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &(pixel[0]));

        QString PixelColor = QColor(pixel[0], pixel[1], pixel[2]).name();
        qDebug() << PixelColor; // => correct value
    }
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
    glDeleteFramebuffers(1, &fbo);
    doneCurrent();
}

但是很明显,当我已经有了一个具有我所需信息的帧缓冲区时,使用另一个帧缓冲区似乎毫无用处。

我还尝试直接读取纹理的值(如@Spektre所建议),但在这种情况下,我总是得到0。

void mouseMoveEvent(QMouseEvent *event)
{
    int x = event->pos().x();
    int y = event->pos().y();

    makeCurrent();
    {
        GLuint texture = textures[TextureIndex::COLOUR];
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexSubImage2D(GL_TEXTURE_2D, 0, x, geometry().height() - y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &(pixel[0]));

        QString PixelColor = QColor(pixel[0], pixel[1], pixel[2]).name();
        qDebug() << PixelColor; // => always 0
    }
    doneCurrent();
}

1 个答案:

答案 0 :(得分:0)

我的方法是正确的,但是我没有绑定到正确的帧缓冲区。

FBOIndex::GEOMETRY是一个枚举值,用于索引FBOs数组,在该数组中我存储了所有帧缓冲对象名称,因此通常它不是正确的帧缓冲对象名称。

我已经定义了一种方法addFBO(index),该方法创建一个帧缓冲区并将其存储在FBOs数组中的位置index上。该方法返回生成的帧缓冲区的帧缓冲区对象名称。如果在位置index上已经存在一个帧缓冲区,则该方法只返回相关的帧缓冲区对象名称。

因此,通过以以下方式更改代码,我终于得到了预期的结果。

void mouseMoveEvent(QMouseEvent *event)
{
    int x = event->pos().x();
    int y = event->pos().y();

    makeCurrent();
    glBindFramebuffer(GL_READ_FRAMEBUFFER, addFBO(FBOIndex::GEOMETRY));
    {
        glReadBuffer(GL_COLOR_ATTACHMENT3);

        QVector<GLubyte> pixel(3);
        glReadPixels(x, geometry().height() - y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &(pixel[0]));

        QString PixelColor = QColor(pixel[0], pixel[1], pixel[2]).name();    
        qDebug() << PixelColor; // => correct value
    }
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
    doneCurrent();
}