在OpenGL中设置相机

5

我已经在制作一个游戏引擎了。一开始我只用SDL实现了2D图形,但是现在我正在逐渐转向使用OpenGL实现3D功能。我看到的大部分有关“如何完成任务”的文档都使用GLUT,而我不使用GLUT。

问题是,我该如何在OpenGL中创建一个“相机”,以便我可以在3D环境中移动并正确地显示3D模型和精灵(例如,具有固定位置和旋转的精灵)?为了设置OpenGL相机,我需要关注哪些函数?这些函数应该按照什么顺序调用?

以下是一些背景信息,解释为什么我需要一个实际的相机。

要绘制一个简单的精灵,我从SDL表面创建一个GL纹理,并将其绘制到屏幕上的坐标为(SpriteX-CameraX)和(SpriteY-CameraY)的位置。这很好用,但是当我开始处理实际的3D模型时,就不太对了。相机的位置是一个自定义的向量类(即不使用标准库),带有X、Y、Z整数组件。

我有一个由三角形构成的3D立方体,单独拿出来,我可以绘制它并旋转它,我实际上可以通过在绘制模型时传入相机位置并使用该位置向量的组件来计算模型的位置来移动立方体(虽然有些别扭)。但是当我尝试旋转模型时,问题就显现出来了。模型的原点不是模型本身,而似乎是屏幕的原点。一些搜索告诉我,我需要保存模型的位置,围绕原点旋转它,然后将模型恢复到其原始位置。

与其通过计算新顶点来计算视口中应该绘制哪些东西,我想创建一个OpenGL“相机”来自动执行此任务,这样我只需要将我的Camera对象的坐标传递给OpenGL相机即可自动翻译视图。如果你使用GLUT,这个任务似乎非常容易,但是我不确定如何仅使用OpenGL设置相机。

编辑 #1(根据一些评论): 以下是我程序中调用的更新方法。它已经更新为创建透视和视图矩阵。所有绘制都在这个方法被调用之前完成。当OpenGL执行时,会执行类似的一组方法(减去缓冲区交换)。x、y、z坐标直接是相机实例及其位置向量。如果相机位于(256, 32, 0),则会将256、32和0传递给Update方法。目前,z被设置为0,因为目前没有办法更改该值。正在绘制的3D模型是一组顶点/三角形+法线,位于X=320,Y=240,Z=-128。当程序运行时,在填充模式下绘制它,然后在线框模式下绘制它,然后在稍微向右移动相机时,在移动后的填充模式下绘制另一个。看起来法线可能是问题的原因,但我认为更多的是我漏掉了一些非常重要的东西,或者没有完全理解glFrustum的NEAR和FAR参数实际上是做什么的。

在我实现这些更改之前,我使用的是glOrtho,立方体渲染正确。现在如果我切换回glOrtho,一个面会渲染(绿色),旋转也很奇怪——可能是由于平移造成的。这个立方体有6种不同的颜色,每个面都有一个。红色、蓝色、绿色、青色、白色和紫色。

int VideoWindow::Update(double x, double y, double z)
{
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    glFrustum(0.0f, GetWidth(), GetHeight(), 0.0f, 32.0f, 192.0f);


    glMatrixMode( GL_MODELVIEW );

    SDL_GL_SwapBuffers();  
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glRotatef(0, 1.0f, 0.0f, 0.0f);
    glRotatef(0, 0.0f, 1.0f, 0.0f);
    glRotatef(0, 0.0f, 0.0f, 1.0f);
    glTranslated(-x, -y, 0);

    return 0;
}

最终编辑: 问题实际上是由于glFrustum函数的近和远参数以及glTranslated函数的Z值引起的。虽然改变这些值已经解决了问题,但我可能需要进一步了解这两个函数之间的关系。

3个回答

5
您需要一个视图矩阵和一个投影矩阵。您可以通过以下两种方式之一实现:
  1. 使用glMatrixMode()glLoadMatrixf()在使用自己的库计算矩阵后自行加载矩阵。

  2. 使用glMatrixMode(GL_MODELVIEW)glTranslate() / glRotate()的组合来创建视图矩阵,以及使用glMatrixMode(GL_PROJECTION)glFrustum()来创建投影矩阵。请记住-您的视图矩阵是相机位置的负平移(因为它是您应该将世界相对于相机原点移动到的位置),以及施加的任何旋转(俯仰/偏航)。

希望这可以帮助您,如果我有更多时间,我会给您写一个适当的示例!

谢谢你给我指明了正确的方向。如果你能看一下我的代码和截图,我已经在帖子中进行了编辑。似乎有些地方还不太对 :) - user29053
实际上,问题确实出在我为glFrustum的Near和Far参数选择的值以及传递到glTranslated的Z值。谢谢。 - user29053

2

你需要使用矩阵堆栈来处理对象层次结构,

但相机位于层次结构内部,因此在绘制对象之前,必须将逆变换放置在堆栈上,因为OpenGL仅使用从3D到相机的矩阵。


1
如果您还没有查看,那么查看以下项目可能会详细解释“tsalter”在他的帖子中写的内容。
来自OGL SDK(CodeColony)的相机
此外,请查看《红皮书》以了解查看和模型视图和投影矩阵如何帮助您创建相机的说明。它从实际相机与对应于OpenGL API的内容之间的良好比较开始。第3章-查看

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