使用glFrustum创建拼接场景

6
我有一个程序,可以根据用户的位置在屏幕上渲染场景。随着用户位置的变化,视锥体会改变以实现非轴投影。我想利用这个技术来在三个不同的显示器上拼接更大的场景,如下所示:
enter image description here 想象一下,在三个显示器上呈现一个大的真实世界场景。每个显示器都应该显示出根据用户位置而改变透视的场景。我已经能够使用一个显示器来根据用户位置渲染场景,但无法想出在三个屏幕上工作的方法。
我创建的非轴投影类基本上执行以下操作:
customCam::project(){
pushMatrices();
glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
        glFrustum(leftNear.x, rightNear.x, bottomNear.y, topNear.y, _near, _far);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(uPos.x, uPos.y, 0, uPos.x, uPos.y, -1, 0, 1, 0); //neglect z scaling for now. In the main program, it's there
    glTranslatef(0, 0, uPos.z);
}

如何将三个棱锥以这样的方式拼接在一起,使场景看起来像现实中一样连续?目前,此类用户按以下方式绘制场景:

cstCam.project();
    //draw something here
popMatriceS(); //which were pushed before glFrustum projection

编辑: 在我的情况下,为了为用户定义三个棱台(考虑到相同参考系中所有显示器的用户和屏幕角),我进行了以下操作:

custCam1.project();
//draw scene here. eg: two walls at the far left and right screen
drawWalls();
popMatrices();
custCam2.project();
drawWalls();
popMatrices();
custCam3.project();
drawWalls();
popMatrices();

void drawWalls(){
//Left most corner screen wall
glBegin(GL_QUADS);
glVertex3f(-1.5*PHWIDTH, HEIGHT/2, 0); //where PHWIDTH, HEIGHT is the physical width/height of each screen
glVertex3f(-1.5*PHWIDTH, HEIGHT/2, -50);
glVertex3f(-1.5*PHWIDTH, -HEIGHT/2, -50);
glVertex3f(-1.5*PHWIDTH, -HEIGHT/2, 0);
glEnd();

//Right most corner screen wall
glBegin(GL_QUADS);
glVertex3f(1.5*PHWIDTH, HEIGHT/2, 0); //where PHWIDTH, HEIGHT is the physical width/height of each screen
glVertex3f(1.5*PHWIDTH, HEIGHT/2, -50);
glVertex3f(1.5*PHWIDTH, -HEIGHT/2, -50);
glVertex3f(1.5*PHWIDTH, -HEIGHT/2, 0);
glEnd();
}
1个回答

1
这并不像看起来那么困难。请参考以下图像(从znear水平向上看的三个屏幕)。

Screens from above

我假设每个屏幕在znear距离时在x方向上跨越2个单位。根据您的场景,您可能需要缩放这个值。
y坐标的范围对于三个屏幕都不会改变,因为它们位于同一垂直位置。
因此,您需要为这些屏幕使用三个不同的投影矩阵。确定偏移非常简单。您只需要相对于摄像机点的差异即可。
left screen   => [-3 - camera.x, -1 - camera.x]
center screen => [-1 - camera.x, 1 - camera.x]
right screen  => [1 - camera.x, 3 - camera.x]

当然,你需要在屏幕空间中获取相机位置,如图所示。

视图矩阵可以是任意的,但对于所有三个屏幕应该是相同的。这次,在场景空间中将相机位置传递给gluLookAt


在第二张截图中,当用户向右移动时,第一摄像机的墙壁开始出现在第二个屏幕上,而且它不会形成连续的场景。然而,我不确定的是,如果这与三个场景中的视图矩阵相同有关吗,就像我上面所做的那样?此外,如果是这种情况,我无法分辨为什么应该为所有三个场景只有一个模型视图矩阵。如果您能够对此解释一下,那将非常不错。 - user1240679
@derhass:对于单个显示器,不对称的棱台和投影似乎是正确的。我用的代码是http://pastebin.com/kLs6yGQA。这里的`begin`和`end`是使用相机的方法,我使用相机进行投影,如`camera1.begin();` //drawing camera1.end。由于它适用于单个显示器,因此可以在本质上将相同的代码用于三个显示器,就像我在编辑中编写的那样。我假设由于它适用于单个显示器,所以当我使用三个显示器时会出现某些错误,但不确定是棱台还是MV矩阵的问题。 - user1240679
@user1240679:你应该知道,你的camera.begin()函数实际上是通过gluLookAt()设置模型视图矩阵。它以一种过于复杂的方式进行设置,并且如果我正确地跟踪了代码,则位置设置错误。如果我正确理解了它,只有在指定SetViewPortalWindow角落的right=-left和top=-bottom时,它才会偶然起作用。 - derhass
@derhass:谢谢。稍后我会通过修改相机类来检查一下,将gluLookAt(_wcUserHead.x, _wcUserHead.y, 0, _wcUserHead.x, _wcUserHead.y, -1)加入其中,看看是否能得到正确的结果。但是关于用户位置的z缩放呢? 2)关于原始问题:通过创建另一个相机类,在begin方法中不使用gluLookAt,我将尝试执行camera1.begin(); camera2.begin() //在此处同时为两个相机执行gluLook camera1.end(); camera2.end(),以便为多个显示器生成单个MV矩阵。我希望我理解得正确,但会及时告诉你。 - user1240679
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/31809/discussion-between-derhass-and-user1240679 - derhass
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接