Print OpenGL texture to file without display?

I am trying to use OpenGL to help with the processing of entering a Kinect depth map into an image. At the moment, we are using Kinect as the main motion sensor, and the program counts how many people go through and removes the screen every time it detects someone new.

The problem is that I need to run this program without access to the display. We want to run it remotely via SSH, and network traffic from other services will be too large to forward X11 to be a good idea. The ability to connect the display to the machine on which the program is running is an opportunity, but we want to avoid this for reasons of energy consumption.

The program creates a 2D texture object for OpenGL and usually just uses GLUT to render before reading pixels and outputting them to a .PNG file using FreeImage. The problem I am facing is that after deleting the GLUT function calls, everything that is printed in .PNG files is just black fields.

I use the OpenNI and NITE drivers for Kinect. The programming language is C ++, and I need to use Ubuntu 10.04 due to the hardware limitations of the target device.

I tried using OSMesa or FrameBuffer objects, but I'm a complete OpenGL newbie, so I didn't get OSMesa to display correctly instead of GLUT functions, and my compilers can't find any OpenGL FrameBuffer functions in GL / glext.h or GL / gl.h .

I know that textures can be read in a program from image files, and all I want to output is one two-dimensional texture. Is there a way to skip the headache of off-screen rendering in this case and print the texture directly to the image file without having to run OpenGL?

+4
source share
3 answers

The OSMesa library is not a replacement for GLUT and cannot work together. If you only need the external part of the rendering without interaction, you must implement a simple event loop yourself.

For instance:

/* 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); 

After that, you can use regular OpenGL calls for rendering and after calling glFinish () , the results can be accessed via the mBuffer pointer.

In the event loop, you can call the usual callbacks onDisplay, onIdle, etc.

+3
source

We want to run it remotely via SSH, and network traffic from other services will be too large to forward X11 to be a good idea.

If you forward X11 and create an OpenGL context on this display, OpenGL traffic will go through the network regardless of whether or not a window exists. So, what you really need (if you want to use an accelerated GPU with an OpenGL GPU), starts the X server on the remote computer and keeps it active VT (that is, the X server should be the program that "owns" the display). Then your program can only connect to this X server itself. But this requires the use of Xlib. Some time ago, the mushroom wrote a minimalist Xlib example, I expanded it a bit to use FBConfigs, you can find it here: https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/x11argb_opengl/x11argb_opengl.c

In your case, you have to do FBO or PBuffer. Never use a visible window framebuffer to display things that need to be stored! If you create an OpenGL window, for example, using the code associated with it, use FBO. Creating a GLuff PBuffer is not much different from creating a GLX window, but it will only be disabled.

The trick is not to use the X Display by default (your SSH forward), but a separate connection to the local X server. The key is a string

 Xdisplay = XOpenDisplay(NULL); 

Instead of NULL, you should pass the connection to the local server. To do this, you will also need to (manually) add an xauth entry or disable xauth on the OpenGL rendering server.

+1
source

You can use glGetTexImage to read textures from OpenGL.

0
source

Source: https://habr.com/ru/post/1385377/


All Articles