首页 > 解决方案 > OpenGL:读取颜色缓冲区

问题描述

我将 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();
}

标签: c++openglgraphicstexturesframebuffer

解决方案


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

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

我已经定义了一个addFBO(index)创建帧缓冲区并将其存储在indexFBOs 数组中的位置的方法。该方法返回生成的帧缓冲区的帧缓冲区对象名称。如果在 position 处已经存在帧缓冲区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();
}

推荐阅读