Распечатать текстуру OpenGL в файл без дисплея?
Я пытаюсь использовать OpenGL, чтобы помочь с обработкой ввода карты глубины Kinect в изображение. На данный момент мы используем Kinect в качестве базового датчика движения, и программа подсчитывает, сколько людей проходит мимо, и делает снимок экрана каждый раз, когда обнаруживает кого-то нового.
Проблема в том, что мне нужно, чтобы эта программа работала без доступа к дисплею. Мы хотим запустить его удаленно через SSH, и сетевой трафик от других сервисов будет слишком большим для перенаправления X11, чтобы быть хорошей идеей. Подключение дисплея к машине, на которой запущена программа, возможно, но мы хотим избежать этого из-за энергопотребления.
Программа генерирует двухмерный текстурный объект для OpenGL и обычно просто использует GLUT для рендеринга перед считыванием пикселей и вывода их в файл.PNG с помощью FreeImage. Проблема, с которой я сталкиваюсь, заключается в том, что после удаления вызовов функций GLUT все, что печатается в файлах.PNG, это просто черные ящики.
Я использую драйверы OpenNI и NITE для Kinect. Язык программирования - C++, и мне нужно использовать Ubuntu 10.04 из-за аппаратных ограничений целевого устройства.
Я пытался использовать объекты OSMesa или FrameBuffer, но я полный новичок в OpenGL, поэтому я не получил OSMesa для правильной визуализации вместо функций GLUT, и мои компиляторы не могут найти ни одну из функций OpenGL FrameBuffer в GL/glext.h или GL/gl.h.
Я знаю, что текстуры могут быть считаны в программу из файлов изображений, и все, что я хочу вывести - это одна двумерная текстура. Есть ли способ пропустить головную боль за пределами экрана рендеринга в этом случае и распечатать текстуру непосредственно в файл изображения без необходимости OpenGL для рендеринга в первую очередь?
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 и т. Д.
Мы хотим запустить его удаленно через SSH, и сетевой трафик от других сервисов будет слишком большим для перенаправления X11, чтобы быть хорошей идеей.
Если вы перенаправите X11 и создадите контекст OpenGL на этом дисплее, трафик OpenGL будет проходить через сеть, независимо от того, есть окно или нет. Итак, что вам действительно нужно сделать (если вы хотите использовать OpenGL с GPU-ускорением), так это запустить 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 Window, только в том, что оно будет за кадром.
Хитрость заключается не в том, чтобы использовать X Display по умолчанию (вашего SSH forward), а в отдельном соединении с локальным X Server. Ключ это линия
Xdisplay = XOpenDisplay(NULL);
Вместо NULL вы бы передавали соединение на локальный сервер. Для этого вам также необходимо (вручную) добавить запись xauth или отключить xauth на сервере рендеринга OpenGL.
Вы можете использовать glGetTexImage для чтения текстуры обратно из OpenGL.