在没有显示的情况下将OpenGL纹理打印到文件?

时间:2011-12-08 16:54:32

标签: c++ opengl

我正在尝试使用OpenGL帮助将Kinect深度图输入处理成图像。目前我们正在使用Kinect作为基本运动传感器,该程序会计算每次有多少人走过并在每次检测到新人时进行屏幕截图。

问题是我需要让这个程序无法访问显示器而运行。我们希望通过SSH远程运行它,而来自其他服务的网络流量对于X11转发而言将是一个好主意。将显示器连接到运行程序的机器是可能的,但我们希望避免因能耗原因这样做。

该程序确实为OpenGL生成2D纹理对象,并且通常在读取像素之前使用GLUT渲染它,并使用FreeImage将它们输出到.PNG文件。我遇到的问题是,一旦删除了GLUT函数调用,打印到.PNG文件的所有内容都只是黑盒子。

我正在使用Kinect的OpenNI和NITE驱动程序。编程语言是C ++,由于目标设备的硬件限制,我需要使用Ubuntu 10.04。

我尝试过使用OSMesa或FrameBuffer对象,但我是一个完整的OpenGL新手,所以我没有让OSMesa正确地代替GLUT函数进行渲染,而我的编译器找不到任何OpenGL FrameBuffer函数在GL / glext.h或GL / gl.h中。

我知道纹理可以从图像文件读入程序,而我想输出的只是一个2-D纹理。有没有办法在这种情况下跳过屏幕外渲染的麻烦,直接将纹理打印到图像文件而不需要OpenGL首先渲染它?

3 个答案:

答案 0 :(得分:3)

OSMesa库既不是GLUT的直接替代品,也不能一起工作。如果您只需要没有交互的屏幕外渲染部分,则必须自己实现一个简单的事件循环。

例如:

/* init OSMesa */
OSMesaContext        mContext;
void                *mBuffer;
size_t               mWidth;
size_t               mHeight;

// Create RGBA context and specify Z, stencil, accum sizes
mContext = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
OSMesaMakeCurrent(mContext, mBuffer, GL_UNSIGNED_BYTE, mWidth, mHeight);

在剪切之后,您可以使用正常的OpenGL调用进行渲染,在 glFinish()调用之后,可以通过 mBuffer 指针访问结果。

在您的事件循环中,您可以调用正常的 onDisplay onIdle 等回调。

答案 1 :(得分:1)

  

我们希望通过SSH远程运行它,而来自其他服务的网络流量对于X11转发来说太过分了。

如果转发X11并在该显示器上创建OpenGL上下文,无论窗口是否可见,OpenGL流量都将通过网络传输。所以你真正需要做的是(如果你想使用GPU加速的OpenGL)是在远程机器上启动一个X服务器,并保持它是活动的VT(即X服务器必须是“拥有”显示器的程序)。然后你的程序只能连接到这个非常X的服务器。但这需要使用Xlib。前段时间 fungus 编写了一个简约的Xlib示例,我稍微扩展了它以便它使用FBConfigs,你可以在这里找到它:https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/x11argb_opengl/x11argb_opengl.c

在你的情况下,你应该渲染到FBO或PBuffer。 永远不要使用可见的窗口帧缓冲区来渲染要存储的东西!如果你创建一个OpenGL窗口,就像我链接的代码一样使用FBO。创建GLX PBuffer与创建GLX窗口没有什么不同,只是它会在屏幕外。

诀窍是,不要使用默认的X Display(SSH转发),而是使用与本地X Server的单独连接。关键是行

Xdisplay = XOpenDisplay(NULL);

而不是NULL,您将连接传递到那里的本地服务器。要使这项工作,您还需要(手动)在OpenGL渲染服务器上添加xauth条目或禁用xauth。

答案 2 :(得分:0)

您可以使用glGetTexImage从OpenGL中读取纹理。