2012-01-22 57 views
1

我想写一个简单的迷宫游戏,不使用任何不赞成的OpenGL API(即没有即时模式)。我使用的是一个顶点缓冲区对象用于每个图块我有我的迷宫,这基本上是四个Vertex个组合:OpenGL第一人称相机旋转和翻译

class Vertex { 
public: 
    GLfloat x, y, z; // coords 
    GLfloat tx, ty; // texture coords 

    Vertex(); 
}; 

并储存在维也纳组织这样的:

void initVBO() 
{ 
    Vertex vertices[4]; 
    vertices[0].x = -0.5; 
    vertices[0].y = -0.5; 
    vertices[0].z = 0.0; 
    vertices[0].tx = 0.0; 
    vertices[0].ty = 1.0; 
    vertices[1].x = -0.5; 
    vertices[1].y = 0.5; 
    vertices[1].z = 0.0; 
    vertices[1].tx = 0.0; 
    vertices[1].ty = 0.0; 
    vertices[2].x = 0.5; 
    vertices[2].y = 0.5; 
    vertices[2].z = 0.0; 
    vertices[2].tx = 1.0; 
    vertices[2].ty = 0.0; 
    vertices[3].x = 0.5; 
    vertices[3].y = -0.5; 
    vertices[3].z = 0.0; 
    vertices[3].tx = 1.0; 
    vertices[3].ty = 1.0; 

    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*4, &vertices[0].x, GL_STATIC_DRAW); 

    ushort indices[4]; 
    indices[0] = 0; 
    indices[1] = 1; 
    indices[2] = 2; 
    indices[3] = 3; 

    glGenBuffers(1, &ibo); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort) * 4, indices, GL_STATIC_DRAW); 
} 

现在,我被卡在相机上。在我的项目的以前版本中,我使用glRotatefglTranslatef来翻译和旋转场景,然后使用glBegin()/glEnd()模式呈现每个图块。但是现在这两个函数已经被弃用了,我没有找到任何有关在仅使用VBOs的上下文中创建摄像头的教程。哪一种是正确的方式?我是否应该根据新的摄像机位置在每个瓦片之间循环修改顶点的位置?

+0

您是否正在使用固定功能管线?另外,在OpenGL中没有相机的概念。将每个顶点与模型 - 视图 - 投影矩阵(其中视图矩阵是您感兴趣的矩阵)相乘。您可以在顶点着色器中执行此操作(如果您使用固定功能管道,则还可以使用矩阵堆栈)。这个问题可能更适合http://gamedev.stackexchange.com/ – Samaursa

+0

@Samaursa正如我所说,我没有使用固定功能的管道,因为从我读过的内容来看,它已经被弃用了。在我的渲染方法中,我基本上绑定了我的VBO并使用'glDrawElements()'方法来渲染它们。此外,'glPopMatrix()'和'glPushMatrix()'方法也被弃用,所以我不知道从哪里开始。 –

+0

看到我的回答(更新了几个编辑 - 为此道歉,我忘了添加其中的一个部分) – Samaursa

回答

2

我将增加datenwolf的答案。我假设只有着色器管道可供您使用。

要求

在OpenGL中4.0+的Opengl不会为你做任何渲染任何作为其移动与固定功能的管线了。如果您现在不使用着色器渲染几何体,则使用弃用的管线。在没有基础框架的情况下启动并运行将是困难的(并非不可能,但我会建议使用基础框架)。作为开始,我会推荐使用GLUT(这将为您创建一个窗口,并具有空闲函数和输入的基本回调),GLEW(设置渲染上下文)和gLTools(矩阵堆栈,通用着色器和着色器管理器快速设置,以便至少可以开始渲染)。

设置

我会在这里给重要的部分,你可以再拼凑。在这一点上,我假设你已经正确设置了GLUT(search for how to set it up),并且你可以用它注册更新循环并创建一个窗口(也就是调用你所选函数之一的循环[注意,这不能是方法]每一帧)。请参阅上面的链接以获得关于此的帮助。

  • 首先,initialize glew(通过调用glewInit()
  • 设置你的场景。这包括使用GLBatch类(来自glTools)创建一组顶点以呈现为三角形,并通过调用其InitializeStockShaders()函数来初始化类(也来自GLTools)及其股票着色器。
  • 在你空闲循环,调用着色经理UseStockShader()功能开始一个新的批次。在顶点批处理中调用draw()函数。有关glTools的完整概述,请参阅go here
  • 不要忘了渲染和分别调用glClear()glSwapBuffers()渲染交换后缓冲器之前清除窗。

注意的大部分功能我给上面接受参数。您应该能够通过查看相应图书馆的文档来了解这些内容。

MVP矩阵(编辑:忘了补充这一部分)

的OpenGL渲染一切,是在低头z轴的1,1坐标。它没有相机的概念,也不关心任何超出这些坐标的东西。模型视图投影矩阵是将你的场景变换为适合这些坐标。

作为一个起点,不用担心这一点,直到你有呈现在屏幕上的东西(确保所有你给你的顶点一批坐标都小于1)。一旦完成,然后使用glTools中的GLFrustum类设置投影矩阵(默认投影是拼写)。你将从这个类中得到你的投影矩阵,你将与你的模型视图矩阵相乘。该模型视图矩阵是模型的转换矩阵和你相机的组合的转型(记住,没有摄像头,所以本质上,你是移动的场景代替)。一旦将所有这些矩阵乘以一个矩阵,就可以使用UseStockShader()函数将它传递给着色器。

使用在GLTools股票着色器(例如GLT_SHADER_FLAT),然后开始创建自己的。

参考

最后,我会极力推荐这本书:OpenGL SuperBible, Comprehensive Tutorial and Reference (Fifth edition - make sure it is this edition)

+0

感谢您提供所有有用的信息。我会将此标记为最好的答案,迄今为止是最完整的答案。 –

4

但是这两个函数现在已被弃用,并且我没有找到任何关于在仅使用VBO的上下文中创建摄像头的教程。

VBOs与此无关。

即时模式和矩阵堆栈是两双不同的鞋子。 VBOs处理获取几何数据给渲染器,矩阵堆栈处理在那里获得转换。这只是受维也纳各组织影响的几何数据。

至于你的问题:你自己计算矩阵,并通过制服将它们传递给着色器。了解OpenGL的矩阵功能从未被GPU加速(除了一台单机,SGI的Onyx)也很重要,所以这甚至没有提供一些性能提升。实际上使用OpenGL的矩阵堆栈会对整体性能产生负面影响,这是由于执行冗余操作,必须在程序中的其他位置完成。

对于一个简单的矩阵数学库看看我linmath.hhttp://github.com/datenwolf/linmath.h

1

如果你真的想坚持使用最新的OpenGL API,其中许多功能,其中赞成可编程管线的去除(OpenGL 4和OpenGL ES 2),你必须自己编写顶点和片段着色器,并在那里实现转换。您将不得不手动创建在着色器中使用的所有属性,特别是您在示例中使用的坐标和纹理坐标。如果您想模仿旧的固定功能OpenGL的行为,您还需要2个统一变量,一个用于模型视图矩阵,另一个用于投影矩阵。

您以前使用的旋转/平移是矩阵运算。在流水线的顶点变换阶段,现在由您提供的顶点着色器执行,您必须将4x4变换矩阵乘以顶点位置(4个坐标,解释为4x1矩阵,其中第4个坐标通常为1,如果您没有这样做任何太花哨)。根据该变换,所得到的矢量将处于正确的相对位置。然后,将投影矩阵乘以该向量,并将结果输出到片段着色器。

您可以通过查看文档glRotateglTranslategluPerspective来了解如何构建所有这些矩阵。记住矩阵乘法是不可计算的,所以你乘以它们的顺序很重要(这就是为什么你称为glRotateglTranslate的顺序也很重要)。

关于学习GLSL和如何使用着色器,我学到了here,但这些教程与OpenGL 1.4和2有关,现在已经很老了。主要区别在于,顶点着色器的预定义输入变量(例如gl_Vertexgl_ModelViewMatrix)不再存在,您必须自己创建它们。