我有一个装有眼动仪的Oculus Rift,可用于根据眼动仪的输入显示实时图像。我想就您在Rift上处理显示的方式征求您的意见(是吗?)。
我有一个简单文本的基本图像,该图像基于眼睛跟踪器的凝视坐标使用OpenCV进行了修改。因此,每次眼动仪输出凝视坐标(60Hz)时,我都会得到一个新图像,就好像我正在使用网络摄像头流一样。我有一个工作程序,但是由于我是OpenGL的新手,所以我希望有人可以按照以下步骤进行操作,以查看是否没有丢失任何东西。我将只在下面包含主要的代码块和书面注释:
1)首先,我创建并绑定(bind)一个纹理。 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循环渲染
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纹理,每帧我都会对其进行修改。我已经阅读了有关帧缓冲区及其使用方法的信息,但是即使在从大量资源中读取后,我也对是否应将它们用于此特定应用程序感到非常困惑。我现在在做什么吗如果有资料来源,您可以推荐了解更多有关此2D应用程序的OpenGL的信息,我将不胜感激。
问题:当前两个屏幕都看到相同的精确图像。这是为什么?两只眼睛不应该看到略有不同的图像吗?我是否没有正确设置眼睛纹理/视口?如果需要,我可以上传整个代码。
当我编写此代码时,我使用的是Rift 0.5.0,但现在我升级到了0.8.0 beta
谢谢!
最佳答案
occulus SDK不会为您创建立体图像对。这里只有两件事值得关注:
当您从SDK查询投影矩阵和视点位置时,实际上并没有执行任何操作。您只需将它们设置为OpenGL投影和模型 View 矩阵,而无需使用它进行任何渲染。
该代码应该渲染到纹理中,为3D世界提供不同的透 View ,并最终使用
ovrHmd_EndFrame
对它进行后处理并渲染到实际的窗口中。但是,您只需提供单视输入纹理作为输入,完全跳过渲染步骤并直接对其进行后处理。
您不能从单个单像图像自动推断出立体图像对。
根据您的评论:
那取决于您如何定义“单眼游戏”。这些游戏大多数都使用3D数据表示并将其渲染到屏幕上,从而创建2D投影。在这种情况下,对于立体输出,必须使用不同的投影和 View 矩阵进行两次渲染。
另一种方法是使用单视场图像和深度缓冲区来创建另一个 View ,方法是将3d点(我们通过深度缓冲区获得)基本上重新投影为完全不同的 View 配置,并填充所有孔。
但是,这些都不适用
如果您只有单眼网络摄像头,则无法直接获取渲染场景不同视角所需的3D信息。有一些方法可以使用视频流的时间相干性来重建此类信息,请参见structure from motion wikipedia artice。但这是非常有限的,不适用于任何实时用途。
关于c++ - Oculus Rift DK2上的简单视频流,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34601009/