本人最近在学OpenGL,对于如何使用VAO,VBO来绘制多个立方体一直没有太多的进展,主要是网上这方面的资料并不多,即使有介绍,实例也没有给出。
今天研究了一下,已经可以画出两个或多个立方体了。效果图见下图。
再攻克多个模型的贴图技术以后,就可以做出一个更逼真的星月绕行的模型出来了(以前太阳,月亮全是用的地球的贴图)。
主要代码:
GLuint vao[1];
GLuint vbo[3];
//立方体6个面 * 2个三角/面 * 3个顶点/三角形 * 3个浮点数/顶点
GLfloat vertices[] = {
-1.0f,1.0f,-1.0f,-1.0f,-1.0f,-1.0f,1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,1.0f,1.0f,-1.0f,-1.0f,1.0f,-1.0f,
1.0f,-1.0f,-1.0f,1.0f,-1.0f,1.0f,1.0f,1.0f,-1.0f,
1.0f,-1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,-1.0f,
1.0f,-1.0f,1.0f,-1.0f,-1.0f,1.0f,1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,-1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,-1.0f,-1.0f,-1.0f,-1.0f,1.0f,1.0f,
-1.0f,-1.0f,-1.0f,-1.0f,1.0f,-1.0f,-1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,1.0f,-1.0f,1.0f,1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,1.0f,
-1.0f,1.0f,-1.0f,1.0f,1.0f,-1.0f,1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,-1.0f,1.0f,1.0f,-1.0f,1.0f,-1.0f
};
//锥体4个面 * 1个三角/面 * 3个顶点/三角形 * 3个浮点数/顶点
GLfloat zuishape[] = {
0.0f,0.0f,1.0f,1.0f,0.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,1.0f,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f,
0.0f,0.0f,0.0f,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f
};
//生成VAO
glGenVertexArrays(1,vao);
//生成VBO
glGenBuffers(3,vbo);
//绑定vao[0]
glBindVertexArray(vao[0]);
//绑定vbo[0]
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
//立方体数据缓存到vbo[0]
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
//数据解释:顶点着色器中location的值;顶点属性的维数;数据的类型;是否数据被标准化;步长,0-让OpenGL自己去识别;起始位置的偏移量
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
//启用指定属性
glEnableVertexAttribArray(0);
//松绑
glBindVertexArray(0);
glBindVertexArray(vao[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
glBindVertexArray(vao[2]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(zuishape), zuishape, GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
//绘图
glBindVertexArray(vao[1]);
glDrawArrays(GL_TRIANGLES,0,36);
glBindVertexArray(0);
//改变立方体在视图中的位置
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX+3, -cameraY, -cameraZ+3));
glUniformMatrix4fv(mvLoc,1,GL_FALSE,glm::value_ptr(vMat));
glBindVertexArray(vao[0]);
//绘制立方体,36个顶点
glDrawArrays(GL_TRIANGLES,0,36);
glBindVertexArray(0);
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX+1, -cameraY+1, -cameraZ+6));
glUniformMatrix4fv(mvLoc,1,GL_FALSE,glm::value_ptr(vMat));
glBindVertexArray(vao[2]);
glDrawArrays(GL_TRIANGLES,0,12);
glBindVertexArray(0);
文件结构如上图,core.h里有enableGL,OpenGLinit,DrawShape等主要函数,GLX定义从opengl32.dll引入的函数列表,主要是取得函数入口地址,main.cpp是主要函数,创建窗口。vertShader.glsl是顶点着色器,fragShader.glsl是片段着色器。编程过程中除系统 opengl32.dll外,不再引用其他dll,窗口也是用CreateWindowEx创建。绿色无依赖。编译后结构如下图。