使用 stbi_write_png 从 OpenGL 帧缓冲区保存的 PNG 向右移动
PNG saved from OpenGL framebuffer using stbi_write_png is shifted to the right
几天来我一直在尝试解决这个视觉错误,但没有成功,所以我问这个问题是想看看是否有人可以帮助我了解发生了什么。
首先我会在没有任何代码的情况下描述问题,然后我会给出一些代码。情况是这样的:
我的 OpenGL 应用程序将此图像渲染到多采样帧缓冲区:
然后我将该多采样帧缓冲区 blit 到常规帧缓冲区(不是多采样帧缓冲区)。
然后我使用 glReadPixels
.
将 RGB 数据从常规帧缓冲区读取到无符号字节数组中
最后,我用无符号字节数组调用stbi_write_png
。这是结果:
在我看来,第一行字节向右移动,这会导致所有其他行移动,从而形成对角线形状。
这是我的代码:
- 创建多重采样帧缓冲区:
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);
请注意,两个帧缓冲区都报告为完整。
要将多重采样帧缓冲区 blit 到常规帧缓冲区,从常规帧缓冲区读取并写入 PNG 图像:
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);
- 注意 glGetError 没有报告错误。
我还没弄清楚哪里出了问题。感谢您的帮助!
问题是 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);
几天来我一直在尝试解决这个视觉错误,但没有成功,所以我问这个问题是想看看是否有人可以帮助我了解发生了什么。
首先我会在没有任何代码的情况下描述问题,然后我会给出一些代码。情况是这样的:
我的 OpenGL 应用程序将此图像渲染到多采样帧缓冲区:
然后我将该多采样帧缓冲区 blit 到常规帧缓冲区(不是多采样帧缓冲区)。
然后我使用
glReadPixels
. 将 RGB 数据从常规帧缓冲区读取到无符号字节数组中
最后,我用无符号字节数组调用
stbi_write_png
。这是结果:
在我看来,第一行字节向右移动,这会导致所有其他行移动,从而形成对角线形状。
这是我的代码:
- 创建多重采样帧缓冲区:
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);
请注意,两个帧缓冲区都报告为完整。
要将多重采样帧缓冲区 blit 到常规帧缓冲区,从常规帧缓冲区读取并写入 PNG 图像:
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);
- 注意 glGetError 没有报告错误。
我还没弄清楚哪里出了问题。感谢您的帮助!
问题是 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);