我正在制作一个OpenGL C++应用程序,用于跟踪用户相对于屏幕的位置,然后将呈现的场景更新为用户的视角。这被称为“桌面VR”,或者您可以将屏幕想象为立体布景或鱼缸。我对OpenGL相当陌生,迄今为止只定义了一个非常简单的场景,只是一个立方体,并且它最初是正确渲染的。OpenGL桌面虚拟现实的非对称Fr 012
问题是,当我开始移动并想要重新渲染立方体场景时,投影平面似乎已经翻译过了,我没有看到我认为我应该做的事。我想要修理这架飞机。如果我正在写一个光线追踪器,我的窗口将永远是固定的,但我的眼睛可以漫步。有人可以向我解释如何让我的相机/眼睛在非原点坐标上漂移时如何达到我想要的效果(固定观看窗口)?
我发现所有的例子都要求相机/眼睛在原点,但这对我来说在概念上并不方便。另外,因为这是一个“鱼缸”,所以我将d_near设置为z = 0的xy平面。
在屏幕/世界空间中,我将屏幕中心分配给(0,0 ,0)以及它的四个角落到: TL(-44.25,25,0) TR(44.25,25,0) BR(44.25,-25,0) BL(-44.25,-25,0) 对于16x9显示器,这些值以厘米为单位。
然后,我使用POSIT计算用户的眼睛(实际上是我脸上的网络摄像头),通常位于(+/- 40,+/- 40,40-250)范围内的某处。我的POSIT方法是准确的。
我正在为透视和查看变换以及使用着色器定义我自己的矩阵。
我初始化如下:
float right = 44.25;
float left = -44.25;
float top = 25.00;
float bottom = -25.00;
vec3 eye = vec3(0.0, 0.0, 100.0);
vec3 view_dir = vec3(0.0, 0.0, -1.0);
vec3 up = vec3(0.0, 1.0, 0.0);
vec3 n = normalize(-view_dir);
vec3 u = normalize(cross(up, n));
vec3 v = normalize(cross(n, u));
float d_x = -(dot(eye, u));
float d_y = -(dot(eye, v));
float d_z = -(dot(eye, n));
float d_near = eye.z;
float d_far = d_near + 50;
// perspective transform matrix
mat4 P = mat4((2.0*d_near)/(right-left), 0, (right+left)/(right-left), 0,
0, (2.0*d_near)/(top-bottom), (top+bottom)/(top-bottom), 0,
0, 0, -(d_far+d_near)/(d_far-d_near), -(2.0*d_far*d_near)/(d_far-d_near),
0, 0, -1.0, 0);
// viewing transform matrix
mat4 V = mat4(u.x, u.y, u.z, d_x,
v.x, v.y, v.z, d_y,
n.x, n.y, n.z, d_z,
0.0, 0.0, 0.0, 1.0);
mat4 MV = C * V;
//MV = V;
从我收集看着网页,我view_dir上最多是保持固定。这意味着我只需要更新d_near和d_far以及d_x,d_y和d_y?我在我的glutIdleFunc中执行此操作(空闲);
void idle (void) {
hBuffer->getFrame(hFrame);
if (hFrame->goodH && hFrame->timeStamp != timeStamp) {
timeStamp = hFrame->timeStamp;
std::cout << "(" << hFrame->eye.x << ", " <<
hFrame->eye.y << ", " <<
hFrame->eye.z << ") \n";
eye = vec3(hFrame->eye.x, hFrame->eye.y, hFrame->eye.z);
d_near = eye.z;
d_far = eye.z + 50;
P = mat4((2.0*d_near)/(right-left), 0, (right+left)/(right-left), 0,
0, (2.0*d_near)/(top-bottom), (top+bottom)/(top-bottom), 0,
0, 0, -(d_far+d_near)/(d_far-d_near), -(2.0*d_far*d_near)/(d_far-d_near),
0, 0, -1.0, 0);
d_x = -(dot(eye, u));
d_y = -(dot(eye, v));
d_z = -(dot(eye, n));
C = mat4(1.0, 0.0, 0.0, eye.x,
0.0, 1.0, 0.0, eye.y,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
V = mat4(u.x, u.y, u.z, d_x,
v.x, v.y, v.z, d_y,
n.x, n.y, n.z, d_z,
0.0, 0.0, 0.0, 1.0);
MV = C * V;
//MV = V;
glutPostRedisplay();
}
}
这里是我的shader代码:
#version 150
uniform mat4 MV;
uniform mat4 P;
in vec4 vPosition;
in vec4 vColor;
out vec4 color;
void
main()
{
gl_Position = P * MV * vPosition;
color = vColor;
}
好吧,我做了一些修改我的代码,但没有成功。当我在顶点着色器中使用V代替MV时,一切看起来都是我想要的,透视图是正确的,并且对象的尺寸是正确的,但是场景是通过摄像头的位移来转换的。
当使用C和V获取MV时,我的场景从观察者的视角直接渲染,渲染的场景按照它应该填充的窗口,但是眼睛/相机的视角丢失。
真的,我想要的是通过适当的眼睛/相机的x和y值来平移2D像素,即投影平面,以保持物体的中心(其xy中心为(0, 0))在渲染图像的中心。我在教科书“交互式计算机图形学:基于Shader的OpenGL(第6版)的自顶向下方法”中得到了指导。使用与网络上免费提供的图书配对的文件,我继续采用主要方法。
当不使用矩阵C创建MV时会拍摄以下图像。当我使用C创建MV时,所有场景看起来像下面的第一张图片。我希望在z中没有翻译,所以我把它作为0。
因为投影平面和我的摄像机平面是平行的,所以从一个坐标系转换到另一个坐标系仅仅是一个平移和inv(T)〜-T。
这里是我的眼睛图像在(0,0,50):
这里是在我的眼睛图像(56,-16,50):
一些视频链接到该项目:[背景](https://www.youtube.com/watch?v=Hnn-uZPdJIY)和[结果](https:/ /www.youtube.com/watch?v=EkRiAxPImeo) –