从后台缓冲区读取像素

3
我想读取后台缓冲区的像素。但是目前我只能得到黑屏(清除颜色)。
问题是,我不需要 glut 窗口来绘制。一旦我获得了像素信息,我就将其传递给另一个程序,该程序将为我绘制图像。
我的 init 函数如下:
// No main function, so no real argv argc
char fakeParam[] = "nothing"; 
char *fakeargv[] = { fakeParam, NULL }; 
int fakeargc = 1; 

glutInit( &fakeargc, fakeargv );
GLenum err = glewInit();

if (GLEW_OK != err)
{
    MessageBoxA(NULL, "Failed to initialize OpenGL", "ERROR", NULL);
}
else
{
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);

    // Not sure if this call is needed since i don't use a glut window to render too..
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

}

然后在我的渲染函数中,我执行以下操作:
void DisplayFunc(void)
{
  /* Clear the buffer, clear the matrix */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // TEAPOT
  glTranslatef(0.0f, 0.0f, -5.0f); // Translate back 5 units
  glRotatef(rotation_degree, 1.0f, 1.0f, 0.0f); // Rotate according to our rotation_degree value

  glFrontFace(GL_CW);
  glutSolidTeapot(1.0f); // Render a teapot
  glFrontFace(GL_CCW);

  glReadBuffer(GL_BACK);
  glReadPixels(0, 0, (GLsizei)1024, (GLsizei)768, GL_RGB, GL_UNSIGNED_BYTE, pixels);

  int r = glGetError();
}

我的工作大致如下。在最后一个函数结束时,我尝试读取所有像素。但输出只是一张黑色的图片。glGetError()没有报错。

有任何想法问题可能是什么吗...???


最好发布完整的程序。如果你渲染到窗口,你能看到图像吗? - BЈовић
2个回答

4
我想读取后备缓冲区的像素。但到目前为止我只得到了一个黑屏(即清除颜色)。
问题是,我不需要使用glut窗口进行绘制。一旦我获得了像素信息,我就会将其传递给另一个程序,该程序将为我绘制图像。
然而事实并非如此。后备缓冲区不是某种离屏渲染区域,它是屏幕窗口的一部分。实际上,整个双缓冲概念只对屏幕窗口有意义。双缓冲窗口的每个像素都有两个颜色值,但只有一个深度、模板等;在缓冲区交换时,只交换后面和前面像素平面的指针。但由于我们仍然在谈论一个窗口,所以在光栅化时,所有片段都要经过像素所有权测试,即检查它们是否实际上可见于屏幕上。如果不是,则不会被渲染。
但你的问题更进一步:你甚至没有创建一个窗口,因此你根本没有OpenGL上下文。你调用OpenGL命令没有任何效果。glReadPixels不会返回任何内容,因为没有东西可以读取。
坏消息是,使用GLUT获取上下文的唯一方法是创建一个窗口。好消息是,你不必使用GLUT。人们,为什么你们不明白这一点:GLUT不是OpenGL的一部分,它只是用于编写小教程的快速而简单的框架。 你需要的是:
- 不是一个窗口,而是一个PBuffer,即一个经过离屏渲染的可绘制区域,不需要经过像素所有权测试。
或者
- 一个隐藏窗口,在其上创建了一个OpenGL上下文,并在该上下文中为离屏渲染目标创建了一个Frame Buffer Object。

谢谢,我现在明白问题了。我也刚刚转换到GLFW,它不需要glutMainLoop。这也是阻碍我的事情之一。我还会检查PBuffer的东西,可能就是我要找的。 - w00
@w00:我认为GLFW也不是你想要的。你仍然需要使用GLFW打开一个(可见的)窗口才能获得上下文。你可能别无选择,只能直接处理更低级别的API,即WGL或GLX。使用WGL创建纯PBuffer有点繁琐。使用GLX创建窗口或PBuffer之间没有复杂度差异。你的目标操作系统是哪个?如果是使用X11/GLX(Linux、FreeBSD)的操作系统,那么我有现成的独立PBuffer创建代码可以提供给你。 - datenwolf

0
尝试在调用glReadPixels之前调用glFlush
另外,你在哪里设置窗口的大小?

@datenwolf:那么任何东西是如何工作的?我自己不使用GLUT,我认为glutInitDisplayMode会正确设置一些东西。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接