使用 stbi_write_png 从 OpenGL 帧缓冲区保存的 PNG 向右移动

PNG saved from OpenGL framebuffer using stbi_write_png is shifted to the right

几天来我一直在尝试解决这个视觉错误,但没有成功,所以我问这个问题是想看看是否有人可以帮助我了解发生了什么。

首先我会在没有任何代码的情况下描述问题,然后我会给出一些代码。情况是这样的:

在我看来,第一行字节向右移动,这会导致所有其他行移动,从而形成对角线形状。

这是我的代码:

   int width        = 450;
   int height       = 450;
   int numOfSamples = 1;

   // Create the multisample framebuffer

   glGenFramebuffers(1, &mMultisampleFBO);

   glBindFramebuffer(GL_FRAMEBUFFER, mMultisampleFBO);

   // Create a multisample texture and use it as a color attachment
   glGenTextures(1, &mMultisampleTexture);

   glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mMultisampleTexture);
   glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numOfSamples, GL_RGB, width, height, GL_TRUE);
   glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);

   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, mMultisampleTexture, 0);

   // Create a multisample renderbuffer object and use it as a depth attachment
   glGenRenderbuffers(1, &mMultisampleRBO);

   glBindRenderbuffer(GL_RENDERBUFFER, mMultisampleRBO);
   glRenderbufferStorageMultisample(GL_RENDERBUFFER, numOfSamples, GL_DEPTH_COMPONENT, width, height);
   glBindRenderbuffer(GL_RENDERBUFFER, 0);

   glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mMultisampleRBO);
   // Create the regular framebuffer

   glGenFramebuffers(1, &mRegularFBO);

   glBindFramebuffer(GL_FRAMEBUFFER, mRegularFBO);

   // Create a texture and use it as a color attachment
   glGenTextures(1, &mRegularTexture);

   glBindTexture(GL_TEXTURE_2D, mRegularTexture);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
   glBindTexture(GL_TEXTURE_2D, 0);

   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mRegularTexture, 0);
   int width  = 450;
   int height = 450;
   static GLubyte* data = new GLubyte[3 * 450 * 450];
   memset(data, 0, 3 * width * height);

   // Blit the multisample framebuffer into the regular framebuffer
   glBindFramebuffer(GL_READ_FRAMEBUFFER, mMultisampleFBO);
   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRegularFBO);
   glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

   // Read from the regular framebuffer into the data array
   glBindFramebuffer(GL_FRAMEBUFFER, mRegularFBO);
   glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);

   // Write the PNG image
   int numOfComponents = 3; // RGB
   int strideInBytes   = width * 3;
   stbi_write_png(imgName.c_str(), width, height, 3, data, width * 3);

我还没弄清楚哪里出了问题。感谢您的帮助!

问题是 glReadPixels 读取图像时一行的对齐方式。默认情况下,图像每一行的起始对齐假定为 4.
由于图片的宽度是450,不能被4整除(450/4 = 112.5),格式是RGB(3字节),所以对齐方式要改一下。

读取图像数据前更改GL_PACK_ALIGNMENT (glPixelStore):

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);