我正在尝试用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);然后没有错误发生,从屏幕上读取像素(但我不需要这样)。
这里可能有什么问题?
答案 0 :(得分:3)
您的问题是 format 参数。对于具有单通道整数内部格式的纹理,正确的参数不是GL_RED
,而是GL_RED_INTEGER
:
glReadPixels(pos.x(), resolution.y() - pos.y(), 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &result);
看看OpenGL documentation wiki(强调我的意思):
...
格式
指定像素数据的格式。对于深度,模板或深度/模板数据的传输,必须在适当的地方使用GL_DEPTH_COMPONENT,GL_STENCIL_INDEX或GL_DEPTH_STENCIL。对于规范化的整数或浮点彩色图像数据的传输,必须使用以下之一:GL_RED,GL_GREEN,GL_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_>数据为NULL并且没有缓冲区绑定到GL_PIXEL_UNPACK_BUFFER),必须为目标图像的内部格式正确设置此参数。
...
注意:official reference page不完整/错误。
答案 1 :(得分: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.
答案 2 :(得分:0)
如果您在Linux上使用NVIDIA的二进制驱动程序并已切换到非图形虚拟控制台(例如 CTRL + ALT + < kbd> F1 )然后任何glReadPixels()
的尝试都将返回GL_INVALID_OPERATION(0x502)。
解决方案:切换回图形控制台(通常 CTRL + ALT + F7 )。