为何用glReadPixels读取GL_COLOR_ATTACHMENT0与GL_BACK的数据不同?
我编写了如下初始化代码:
void init() {... glGenRenderbuffers(1, &colorPattern); glBindRenderbuffer(GL_RENDERBUFFER, colorPattern); glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA,outputSize[0],outputSize[1]); glGenRenderbuffers(1, &depthPattern); glBindRenderbuffer(GL_RENDERBUFFER, depthPattern); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, outputSize[0], outputSize[1]); glGenFramebuffers(1, &patternFrame); glBindFramebuffer(GL_FRAMEBUFFER, patternFrame); glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER, colorPattern); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthPattern); glDrawBuffer(GL_COLOR_ATTACHMENT0); }
随后,我在主帧缓冲(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);)和自定义帧缓冲(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, patternFrame);)中均启用GL_BLEND进行绘制。最后通过glReadPixels()读取数据:
void display(){ ... glBindFramebuffer(GL_DRAW_FRAMEBUFFER, patternFrame); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_POINTS, 0, Num); glBindFramebuffer(GL_READ_FRAMEBUFFER, patternFrame); glReadBuffer(GL_COLOR_ATTACHMENT0); float test[4]; glReadPixels(20, 200, 1, 1, GL_RGBA, GL_FLOAT, test); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_POINTS, 0, Num); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glReadBuffer(GL_BACK); glReadPixels(20, 200, 1, 1, GL_RGBA, GL_FLOAT, test); }
我发现patternFrame(GL_COLOR_ATTACHMENT0)与主帧缓冲(GL_BACK)对应位置的RGBA通道数据存在差异:patternFrame的alpha通道为0到1之间的小数,而主帧缓冲的alpha通道恒为1。请问这是什么原因?
原因分析
主帧缓冲的Alpha通道默认处理
窗口系统提供的主帧缓冲,其底层颜色格式通常不包含Alpha通道(比如实际是GL_RGB格式),或者窗口管理器会自动忽略写入的Alpha值,甚至强制将Alpha通道固定为1。因为绝大多数桌面场景不需要窗口内容的Alpha来做合成,所以硬件或驱动会直接覆盖Alpha值。自定义帧缓冲的存储格式支持Alpha
你创建的自定义颜色渲染缓冲明确指定了GL_RGBA格式,这个格式完整保留RGBA四个通道的数据,绘制时的Alpha计算结果会被正确写入,读取自然能得到0-1之间的原始值。混合设置不影响主帧缓冲的Alpha强制行为
虽然两个帧缓冲都启用了GL_BLEND,但混合逻辑的结果是否保留Alpha,只影响自定义帧缓冲。主帧缓冲的Alpha被设为1是窗口系统的处理规则,和混合参数无关。验证方法
可以调用glGetFramebufferAttachmentParameteriv查询主帧缓冲的格式细节:
GLint format; glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_FORMAT, &format);
会发现主帧缓冲的格式大概率是不带Alpha的类型,或者Alpha通道被硬件忽略。
内容的提问来源于stack exchange,提问作者Chris

