У меня есть Oculus Rift, оснащенный трекером глаз, который я использую для отображения изображений в реальном времени на основе входных данных трекера глаз. Я хотел узнать ваше мнение о том, как я работаю с дисплеем в Rift (правильно ли это?).
У меня есть базовое изображение простого текста, которое изменяется с помощью OpenCV на основе координат взгляда из устройства отслеживания глаз. Таким образом, каждый раз, когда айтрекер выводит координаты взгляда (60 Гц), у меня появляется новое изображение, как будто я работаю с потоком веб-камеры. У меня есть рабочая программа, но, поскольку я новичок в OpenGL, я надеялся, что кто-нибудь сможет выполнить следующие шаги, чтобы увидеть, не упустил ли я что-то. Я включу только основные фрагменты кода с письменными комментариями ниже:
1) Сначала я создаю и привязываю текстуру. matToTexture — это функция, которая преобразует изображение cv::mat в текстуру.
tex = matToTexture(result, GL_NEAREST, GL_NEAREST, GL_CLAMP);
glBindTexture(GL_TEXTURE_2D, tex)
2) Затем я делаю буферы рендеринга глаз и настраиваю компоненты VR, получаю позы глаз и т.д.:
for (int eye=0; eye<2; eye++)
{
idealSize = ovrHmd_GetFovTextureSize(hmd, (ovrEyeType)eye, hmd->DefaultEyeFov[eye], 1.0f);
EyeRenderTexture[eye] = tex;
//EyeRenderViewport[eye].Pos.x = 0;
EyeRenderViewport[0].Pos.x =0;
EyeRenderViewport[1].Pos.x = idealSize.w/2;
EyeRenderViewport[eye].Pos.y = 0;
EyeRenderViewport[eye].Size = idealSize;
}
//Setup VR components
ovrGLConfig oglcfg;
oglcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
oglcfg.OGL.Header.BackBufferSize.w = hmd->Resolution.w;
oglcfg.OGL.Header.BackBufferSize.h = hmd->Resolution.h;
oglcfg.OGL.Header.Multisample = 1;
oglcfg.OGL.Window = handle;
oglcfg.OGL.DC = GetDC(handle);
if (!ovrHmd_ConfigureRendering(hmd, &oglcfg.Config,
ovrDistortionCap_Vignette |
ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive,
hmd->DefaultEyeFov, EyeRenderDesc))
return(1);
//Getting eye pose outside the loop since our pose will remain static
ovrVector3f useHmdToEyeViewOffset[2]= {EyeRenderDesc[0].HmdToEyeViewOffset, EyeRenderDesc[1].HmdToEyeViewOffset};
ovrHmd_GetEyePoses(hmd, 0, useHmdToEyeViewOffset, EyeRenderPose, NULL);
glGenTextures(1, &textureID);
//Changing eye tracking location from 1920-1080 to 2364-1461 since that is
//optimal buffer size
float x_scale = static_cast<float>(image.cols)/static_cast<float>(hmd->Resolution.w);
float y_scale = static_cast<float>(image.rows)/static_cast<float>(hmd->Resolution.h);
//x_adjusted and y_adjusted store the new adjusted x,y values
float x_adjusted, y_adjusted;
Наконец, у меня есть цикл рендеринга
while(1)
{
//Changing the texture dynamically because the result image is changing
//with eye tracker input
tex = matToTexture(result, GL_NEAREST, GL_NEAREST, GL_CLAMP);
glBindTexture(GL_TEXTURE_2D, tex);
for (int eye = 0; eye<2; eye++)
{
projection[eye] = ovrMatrix4f_Projection(EyeRenderDesc[eye].Fov, 1, 1000, 1);
glMatrixMode(GL_PROJECTION);
glLoadTransposeMatrixf(projection[eye].M[0]);
EyeRenderTexture[eye] = tex;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(EyeRenderDesc[eye].HmdToEyeViewOffset.x,-EyeRenderDesc[eye].HmdToEyeViewOffset.y, EyeRenderDesc[eye].HmdToEyeViewOffset.z);
//Distortion Rendering
eyeTexture[eye].OGL.Header.API = ovrRenderAPI_OpenGL;
//eyeTexture[eye].OGL.Header.TextureSize = idealSize;
eyeTexture[eye].OGL.Header.TextureSize.h = idealSize.h;
eyeTexture[eye].OGL.Header.TextureSize.w = 2*idealSize.w;
eyeTexture[eye].OGL.Header.RenderViewport.Size = idealSize;
eyeTexture[0].OGL.Header.RenderViewport.Pos.x = 0;
eyeTexture[1].OGL.Header.RenderViewport.Pos.x = idealSize.w;
eyeTexture[eye].OGL.Header.RenderViewport.Pos.y = 0;
eyeTexture[eye].OGL.TexId = EyeRenderTexture[eye];
}
ovrHmd_EndFrame(hmd, EyeRenderPose, &eyeTexture[0].Texture);
//restoring result back to original so that new scotoma position
//can be added onto it
image.copyTo(result);
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//Exiting loop if 'q' is pressed
if (quit == 1) break;
}
glDeleteTextures(1, &tex);
Итак, у меня есть только одна текстура OpenGL, которую я изменяю с каждым кадром. Я читал о буферах кадра и о том, как их можно использовать, но даже после прочтения множества источников я очень запутался, следует ли их использовать для этого конкретного приложения. То, что я делаю, в порядке? Если есть источник, который вы можете порекомендовать, чтобы узнать больше об OpenGL для этого 2D-приложения, я был бы признателен.
ВОПРОС: Оба экрана в настоящее время видят одно и то же точное изображение. Это почему? Разве оба глаза не должны видеть немного разные изображения? Я неправильно настроил текстуры/окна просмотра? Если нужно, могу выложить весь код.
Когда я писал этот код, я использовал Rift 0.5.0, но теперь я обновился до бета-версии 0.8.0.
Спасибо!