7

我正在尝试使用 FBO 实现颜色选择。我有用于渲染场景的多重采样 FBO (fbo[0]),我有用于颜色拾取的非多重采样 FBO (fbo[1])。

问题是:当我尝试从 fbo[1] 读取像素数据时,一切顺利,直到 glReadPixels 调用设置 GL_INVALID_OPERATION 标志。我查了手册,找不到原因。

创建 FBO 的代码:

glBindRenderbuffer(GL_RENDERBUFFER, rbo[0]);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, resolution[0], resolution[1]);
glBindRenderbuffer(GL_RENDERBUFFER, rbo[1]);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_DEPTH24_STENCIL8, resolution[0], resolution[1]);
glBindRenderbuffer(GL_RENDERBUFFER, rbo[2]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_R32UI, resolution[0], resolution[1]);
glBindRenderbuffer(GL_RENDERBUFFER, rbo[3]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, resolution[0], resolution[1]);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);   
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[3]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[2]);
OGLChecker::checkFBO(GL_DRAW_FRAMEBUFFER);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[0]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[0]);
OGLChecker::checkFBO(GL_DRAW_FRAMEBUFFER);

我的检查器保持沉默,因此 FBO 已完成。接下来是拣货代码

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// bla, bla, bla
// do the rendering
unsigned int result;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[1]);
int sb;
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glGetIntegerv(GL_SAMPLE_BUFFERS, &sb);
//    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
OGLChecker::getGlError();
std::cerr << "Sample buffers " << sb << std::endl;
glReadPixels(pos.x(), resolution.y() - pos.y(), 1, 1, GL_RED, GL_UNSIGNED_INT, &result);
OGLChecker::getGlError();
return result;

输出:

Sample buffers 0
OpenGL Error : Invalid Operation

有趣的事实是,如果我取消注释 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 然后不会发生错误并且从屏幕读取像素(但我不需要这个)。

这里可能有什么问题?

4

3 回答 3

3

你的问题是格式参数。对于具有单通道整数内部格式的纹理,正确的参数不是GL_RED,而是GL_RED_INTEGER

glReadPixels(pos.x(), resolution.y() - pos.y(), 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &result);

查看OpenGL 文档 wiki(重点是我的):

...

格式

指定像素数据的格式。对于深度、模板或深度/模板数据的传输,您必须在适当的情况下使用 GL_DEPTH_COMPONENT、GL_STENCIL_INDEX 或 GL_DEPTH_STENCIL。对于标准化整数或浮点彩色图像数据的传输,您必须使用以下之一:GL_RED、GL_GREEN、G​​L_BLUE、GL_RG、GL_RGB、GL_BGR、GL_RGBA 和 GL_BGRA。对于非标准化整数数据的传输,您必须使用以下之一:GL_RED_INTEGER、GL_GREEN_INTEGER、GL_BLUE_INTEGER、GL_RG_INTEGER、GL_RGB_INTEGER、GL_BGR_INTEGER、GL_RGBA_INTEGER 和 GL_BGRA_INTEGER。即使没有进行实际的像素传输(数据为 NULL 并且没有缓冲区绑定到 GL_PIXEL_UNPACK_BUFFER),您也必须为目标图像的内部格式正确设置此参数。

...


注意:官方参考页面不完整/错误。

于 2019-03-13T12:24:35.660 回答
0

如果您在 Linux 上使用 NVIDIA 的二进制驱动程序并已切换到非图形虚拟控制台(例如CTRL++ ALTF1,那么任何尝试都glReadPixels()将返回 GL_INVALID_OPERATION (0x502)。

解决方案:切换回图形控制台(通常是CTRL+ ALT+ F7)。

于 2014-03-20T22:03:36.667 回答
0

鉴于如果您取消注释该代码行,它是“固定的”,我想知道您的驱动程序是否对您撒谎说 GL_SAMPLE_BUFFERS 为 0。来自http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml

GL_INVALID_OPERATION is generated if GL_READ_FRAMEBUFFER_BINDING is non-zero, the read framebuffer is complete, and the value of GL_SAMPLE_BUFFERS for the read framebuffer is greater than zero.
于 2012-11-27T23:59:37.270 回答