来自FBO的glReadPixels因多重采样而失败

时间:2021-08-21 18:49:02

I have an FBO object with a color and depth attachment which I render to and then read from using glReadPixels() and I'm trying to add to it multisampling support.
Instead of glRenderbufferStorage() I'm calling glRenderbufferStorageMultisampleEXT() for both the color attachment and the depth attachment. The frame buffer object seem to have been created successfully and is reported as complete.
After rendering I'm trying to read from it with glReadPixels(). When the number of samples is 0 i.e. multisampling disables it works perfectly and I get the image I want. when I set the number of samples to something else, say 4, the frame buffer is still constructed OK but glReadPixels() fails with an INVALID_OPERATION

我有一个带有颜色和深度附件的FBO对象,我使用glReadPixels()进行渲染然后读取,我正在尝试添加多重采样支持。而不是glRenderbufferStorage()我正在为颜色附件和深度附件调用glRenderbufferStorageMultisampleEXT()。帧缓冲区对象似乎已成功创建并报告为完成。渲染后我试图用glReadPixels()读取它。当样本数为0时,即多重采样禁用,它完美地工作,我得到我想要的图像。当我将样本数量设置为其他值时,比如4,帧缓冲区仍然构造正常,但glReadPixels()失败并带有INVALID_OPERATION

Anyone have an idea what could be wrong here?

任何人都知道这里有什么问题吗?

EDIT: The code of glReadPixels:

编辑:glReadPixels的代码:

glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptr);

where ptr points to an array of width*height uints.

其中ptr指向一个宽度为* height uints的数组。

2 个解决方案

#1


I don't think you can read from a multisampled FBO with glReadPixels(). You need to blit from the multisampled FBO to a normal FBO, bind the normal FBO, and then read the pixels from the normal FBO.

我不认为你可以用glReadPixels()读取多重采样的FBO。您需要从多重采样FBO blit到普通FBO,绑定普通FBO,然后从普通FBO读取像素。

Something like this:

像这样的东西:

// Bind the multisampled FBO for reading
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, my_multisample_fbo);
// Bind the normal FBO for drawing
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, my_fbo);
// Blit the multisampled FBO to the normal FBO
glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
//Bind the normal FBO for reading
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, my_fbo);
// Read the pixels!
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

#2


You can't read the multisample buffer directly with glReadPixels since it would raise an GL_INVALID_OPERATION error. You need to blit to another surface so that the GPU can do a downsample. You could blit to the backbuffer, but there is the problem of the "pixel owner ship test". It is best to make another FBO. Let's assume you made another FBO and now you want blit. This requires GL_EXT_framebuffer_blit. Typically, when your driver supports GL_EXT_framebuffer_multisample, it also supports GL_EXT_framebuffer_blit, for example the nVidia Geforce 8 series.

您无法直接使用glReadPixels读取多重采样缓冲区,因为它会引发GL_INVALID_OPERATION错误。您需要向另一个表面进行blit,以便GPU可以进行下采样。您可以对后备缓冲器进行blit,但是存在“像素所有者发货测试”的问题。最好再做一个FBO。让我们假设你做了另一个FBO,现在你想要blit。这需要GL_EXT_framebuffer_blit。通常,当您的驱动程序支持GL_EXT_framebuffer_multisample时,它还支持GL_EXT_framebuffer_blit,例如nVidia Geforce 8系列。

 //Bind the MS FBO
 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, multisample_fboID);
 //Bind the standard FBO
 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboID);
 //Let's say I want to copy the entire surface
 //Let's say I only want to copy the color buffer only
 //Let's say I don't need the GPU to do filtering since both surfaces have the same dimension
 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
 //--------------------
 //Bind the standard FBO for reading
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
 glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);

Source: GL EXT framebuffer multisample

来源:GL EXT帧缓冲多重采样

#1


I don't think you can read from a multisampled FBO with glReadPixels(). You need to blit from the multisampled FBO to a normal FBO, bind the normal FBO, and then read the pixels from the normal FBO.

我不认为你可以用glReadPixels()读取多重采样的FBO。您需要从多重采样FBO blit到普通FBO,绑定普通FBO,然后从普通FBO读取像素。

Something like this:

像这样的东西:

// Bind the multisampled FBO for reading
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, my_multisample_fbo);
// Bind the normal FBO for drawing
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, my_fbo);
// Blit the multisampled FBO to the normal FBO
glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
//Bind the normal FBO for reading
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, my_fbo);
// Read the pixels!
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

#2


You can't read the multisample buffer directly with glReadPixels since it would raise an GL_INVALID_OPERATION error. You need to blit to another surface so that the GPU can do a downsample. You could blit to the backbuffer, but there is the problem of the "pixel owner ship test". It is best to make another FBO. Let's assume you made another FBO and now you want blit. This requires GL_EXT_framebuffer_blit. Typically, when your driver supports GL_EXT_framebuffer_multisample, it also supports GL_EXT_framebuffer_blit, for example the nVidia Geforce 8 series.

您无法直接使用glReadPixels读取多重采样缓冲区,因为它会引发GL_INVALID_OPERATION错误。您需要向另一个表面进行blit,以便GPU可以进行下采样。您可以对后备缓冲器进行blit,但是存在“像素所有者发货测试”的问题。最好再做一个FBO。让我们假设你做了另一个FBO,现在你想要blit。这需要GL_EXT_framebuffer_blit。通常,当您的驱动程序支持GL_EXT_framebuffer_multisample时,它还支持GL_EXT_framebuffer_blit,例如nVidia Geforce 8系列。

 //Bind the MS FBO
 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, multisample_fboID);
 //Bind the standard FBO
 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboID);
 //Let's say I want to copy the entire surface
 //Let's say I only want to copy the color buffer only
 //Let's say I don't need the GPU to do filtering since both surfaces have the same dimension
 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
 //--------------------
 //Bind the standard FBO for reading
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
 glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);

Source: GL EXT framebuffer multisample

来源:GL EXT帧缓冲多重采样