glReadPixels - 图像看起来抖动
我希望捕获在 openGL 中渲染的图像。我使用 glReadPixels,然后使用 CImg 保存图像。不幸的是,结果是错误的。见下文。左边的图像是正确的。我用 GadWin PrintScreen 捕获了它。右图不正确。我用 glReadPixels 和 CImg 创建它:
我已经对可能出现的问题进行了大量的网络研究,但我没有办法去追求。这里是捕获图像的代码:
void snapshot() {
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
int bytes = width*height*3; //Color space is RGB
GLubyte *buffer = (GLubyte *)malloc(bytes);
glFinish();
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glFinish();
CImg<GLubyte> img(buffer,width,height,1,3,false);
img.save("ScreenShot.ppm");
exit(0);
}
这是我调用快照方法的地方:
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawIndividual(0);
snapshot();
glutSwapBuffers();
}
根据评论,我获取了位深度并打印到控制台。结果如下:
redbits=8
greenbits=8
bluebits=8
depthbits=24
I wish to capture an image I rendered rendered in openGL. I use glReadPixels and then save the image with CImg. Unfortunately, the result is wrong. See below. The image on the left is correct. I captured it with GadWin PrintScreen. The image on the right is incorrect. I created it with glReadPixels and CImg:
I've done a lot of Web research on what might be wrong, but I'm out of avenues to pursue. Here the code the captures the image:
void snapshot() {
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
int bytes = width*height*3; //Color space is RGB
GLubyte *buffer = (GLubyte *)malloc(bytes);
glFinish();
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glFinish();
CImg<GLubyte> img(buffer,width,height,1,3,false);
img.save("ScreenShot.ppm");
exit(0);
}
Here is where I call the snapshot method:
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawIndividual(0);
snapshot();
glutSwapBuffers();
}
Following up on a comment, I grabbed the bit depth and printed to the console. Here are the results:
redbits=8
greenbits=8
bluebits=8
depthbits=24
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您显然是从帧缓冲区获取图像,但行长度似乎不对。您设置了打包对齐(很好),但还有更多可设置的参数:
将它们设置为 0 以实现紧密打包。 glReadPixels() 之后的 glFinish() 也是多余的。 glReadPixels 不能异步工作 - 它仅在读取数据复制到目标缓冲区后返回(或者在写入 PBO 的情况下,从 PBO 获取数据将等待操作完成)。
You're clearly getting the image from the framebuffer, but the row length seems off. You set the packing alignment (good), but there are more settable parameters:
set them to 0 for tight packing. Also the glFinish() after glReadPixels() is superflous. glReadPixels doesn't work asynchronously – it returns only after the read data has been copied into the target buffer (or in the case of writing to a PBO, fetching the data from the PBO will wait for the operation to finish).
CImg 不会交织其颜色。也就是说,3个红、绿、蓝像素将线性存储为:
R1,R2,R3,...,G1,G2,G3,...,B1,B2,B3,...
但是,OpenGL的glReadPixel和glDrawPixel 期望交错的颜色分量如下所示:
R1、G1、B1、R2、G2、B2...
此外,OpenGL 将原点 (0,0) 放在图像的左下角。 CImg 使用 more 方法,其中原点位于图像的左上角。
这是我编写的一个例程,用于将交错颜色转换为 CImg 的面向通道的格式。
我可能应该添加代码来解释原点的变化,但我感到懒惰并决定使用 CImg 来做到这一点。一旦运行此例程,此代码就会创建图像对象:
据我所知,我不必设置任何打包参数。下面是我用来从 OpenGL 渲染目标获取像素的代码:
CImg does not interleave its colors. That is, 3 red, green, blue pixels would be stored linearly as:
R1, R2, R3, ..., G1, G2, G3, ..., B1, B2, B3, ...
However, OpenGL's glReadPixel and glDrawPixel expect interleaved color components like this:
R1, G1, B1, R2, G2, B2, ...
Additionally, OpenGL puts the origin (0,0) at the lower left corner of an image. CImg uses the more approach where the origin is at the top left of the image.
Here is a routine I wrote convert the interleaved colors to CImg's channel-oriented format.
I should have probably added the code to account for the change in origin, but I felt lazy and decided to use CImg to do that. Once this routine is run, this code creates the image object:
And as far as I can tell, I do not have to set any packing parameters. Here is the code I use to grab the pixels from the OpenGL render target: