我试图编写一个简单的迷宫游戏,而不使用任何弃用的OpenGL API(即没有立即模式)。我为迷宫中的每个瓷砖使用了一个顶点缓冲区对象,这实际上是四个Vertex
的组合:
class Vertex {
public:
GLfloat x, y, z; // coords
GLfloat tx, ty; // texture coords
Vertex();
};
并存储在这样的VBO中:
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);
}
现在,我一直坚持相机运动。在我项目的先前版本中,我使用glRotatef
和glTranslatef
来翻译和旋转场景,然后使用glBegin()
/ glEnd()
模式渲染每个图块。但是这两个函数现在已被弃用,我没有找到任何关于仅使用VBO在上下文中创建摄像头的教程。哪种方法正确?我应该根据新的摄像机位置在每个修改顶点位置的图块之间循环吗?
答案 0 :(得分:4)
维多利亚州立大学与此毫无关系。但这两个函数现已弃用,我没有找到任何关于仅使用VBO在上下文中创建相机的教程。
立即模式和矩阵堆叠是两双不同的鞋子。 VBO处理将几何数据提供给渲染器,矩阵堆栈处理在那里进行转换。它只是受VBO影响的几何数据。
至于你的问题:你自己计算矩阵并通过制服将它们传递给着色器。同样重要的是要理解OpenGL的矩阵函数从未被GPU加速(除了一台机器,SGI的Onyx),所以这甚至没有提供一些性能提升。实际上,由于执行冗余操作,使用OpenGL的矩阵堆栈会对整体性能产生负面影响,这也必须在程序中的其他位置完成。
对于简单的矩阵数学库,请查看我的linmath.h
http://github.com/datenwolf/linmath.h
答案 1 :(得分:2)
我将添加到datenwolf的答案。我假设只有着色器管道可用。
<强>要求强>
在OpenGL 4.0+中,当Opengl离开固定功能管道时,它不会为您做任何渲染。如果您现在正在使用着色器渲染几何体,那么您正在使用已弃用的管道。没有一些基础框架的启动和运行将是困难的(并非不可能,但我建议使用基础框架)。作为开始,我建议使用GLUT(这将为您创建一个窗口并具有空闲函数和输入的基本回调),GLEW(设置渲染上下文)和{{3 (矩阵堆栈,通用着色器和着色器管理器,用于快速设置,以便您至少可以开始渲染)。
<强>设置强>
我将在这里给出重要的部分,然后你可以拼凑起来。此时我假设您正确设置了GLUT(gLTools)并且您可以使用它注册更新循环并创建一个窗口(即调用您所选函数之一的循环[注意,这不是一个方法]每一帧)。请参阅上面的链接以获取相关帮助。
glewInit()
)InitializeStockShaders()
功能。UseStockShader()
功能以启动新批处理。调用顶点批次上的draw()
函数。有关glTools的完整概述,initialize glew。glClear()
和glSwapBuffers()
来渲染缓冲区。请注意,我上面给出的大多数函数都接受参数。您应该能够通过查看相应的图书馆文档来解决这些问题。
MVP矩阵(编辑:忘记添加此部分)
OpenGL渲染-1,1坐标中的所有内容,向下看z轴。它没有相机的概念,也不关心任何超出这些坐标的东西。模型 - 视图 - 投影矩阵将您的场景转换为 fit 这些坐标。
作为一个起点,在屏幕上显示某些内容之前不要担心这一点(确保您为顶点批次提供的所有坐标都小于1)。完成后,使用glTools中的GLFrustum
类设置投影矩阵(默认投影为正交投影)。您将从此类中获取投影矩阵,您将与模型视图矩阵相乘。模型 - 视图矩阵是模型的变换矩阵和摄像机的变换的组合(记住,没有摄像机,所以基本上,你正在移动场景)。将所有这些矩阵相乘以生成一个矩阵后,使用UseStockShader()
函数将其传递给着色器。
在GLTools中使用股票着色器(例如GLT_SHADER_FLAT
),然后开始创建自己的着色器。
<强>参考强>
最后,我强烈建议您阅读本书:go here
答案 2 :(得分:1)
如果您真的想要坚持使用最新的OpenGL API,其中许多功能被移除以支持可编程管道(OpenGL 4和OpenGL ES 2),您将不得不自己编写顶点和片段着色器,并实现在那里改造的东西。您必须手动创建在着色器中使用的所有属性,特别是您在示例中使用的坐标和纹理坐标。如果你想模仿旧的固定功能OpenGL的行为,你还需要2个统一变量,一个用于模型视图矩阵,另一个用于投影矩阵。
您以前的旋转/平移是矩阵运算。在管道的顶点变换阶段,现在由您提供的顶点着色器执行,您必须将4x4变换矩阵乘以顶点位置(4个坐标,解释为4x1矩阵,其中第4个坐标通常为1,如果您不这样做任何太花哨的东西)。根据该变换,得到的矢量将处于正确的相对位置。然后将投影矩阵乘以该向量,并将结果输出到片段着色器。
通过查看glRotate
,glTranslate
和gluPerspective
的文档,您可以了解如何构建所有这些矩阵。记住矩阵乘法是非可变的,所以你乘以它们的顺序很重要(这正是你调用glRotate
的顺序的原因。
glTranslate
也很重要。)
关于学习GLSL以及如何使用着色器,我在here上学到了,但这些教程与OpenGL 1.4和2有关,现在已经很老了。主要区别在于顶点着色器的预定义输入变量(例如gl_Vertex
和gl_ModelViewMatrix
)不再存在,您必须自己创建它们。