我有一个Oculus裂谷安装了一个眼睛跟踪器,我用来显示实时图像的基础上的眼睛跟踪器输入。我想听听你对我处理裂口显示器的方式的看法(对吗?)
我有一个简单文本的基本图像,它是基于眼睛跟踪器的凝视坐标使用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循环。
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测试版
谢谢!
发布于 2016-01-05 22:03:02
问:这两个屏幕目前都能看到相同的图像。为什么会这样呢?两只眼睛不应该看到稍微不同的图像吗?
occulus不会为您创建立体图像对。这里有两件事是值得关注的:
当您从SDK查询投影矩阵和视点位置时,实际上您并没有对它做任何事情。您只需将它们设置为OpenGL投影和模型视图矩阵,而不使用它呈现任何内容。
代码应该呈现到纹理中,向3D世界提供不同的透视图,最后使用ovrHmd_EndFrame对其进行后处理,并将其呈现到实际窗口。
然而,您只是提供您的单目输入纹理作为输入,完全跳过渲染步骤,并直接后处理它。
您不能从单个单目图像自动推导出立体图像对。
根据你的评论:
我知道这不会是真实的3D,但我想知道,例如,一个单一的电脑游戏图像如何可以被修改,以显示轻巧的不同视图左眼与右眼。
这取决于你如何定义“单观游戏”。这些游戏大多使用3D数据表示,并将其呈现到屏幕上,创建一个2D投影。在这种情况下,对于立体输出,渲染必须用不同的投影和视图矩阵进行两次。
另一种方法是使用单目图像和深度缓冲器创建另一个视图,方法是基本上重新投影3d点(我们通过深度缓冲区获得),以非常不同的视图配置,并填充所有的洞。
然而,所有这些都不适用于
我有一个新的形象,所以这是我工作的一个网络摄像头流。
如果你只有一个单一的摄像头,你没有直接的方式获得3D信息所需的渲染一个不同的视角的场景。有一些方法可以利用视频流的时间相干性来重建这些信息,参见结构从运动维基百科停战。但这是非常有限的,不适用于任何实时使用。
https://stackoverflow.com/questions/34601009
复制相似问题