多个glBindBuffer和glDrawXXX 需要glBindVertexArray VAO指定

来源:互联网 发布:js 数组 removeall 编辑:程序博客网 时间:2024/06/06 02:37
一个VAO有多个VBO,它们之间也是通过上下文,只有唯一的激活VAO,在VAO后创建的VBO都属于该VAO。
关联VBO数据用取得当前激活的缓存区对象偏移来指定。

VAO是一个对象,其中包含一个或者更多的Vertex Buffer Objects。而VBO是Graphics Card中的一个内存缓冲区,用来保存顶点信息,颜色信息,法线信息,纹理坐标信息和索引信息等等。VAO在Graphics Card线性的存储几个对象信息,替代了以前发送我们需要的数据到Graphics Card上,这也是Direct3D没有立即模式情况下工作的方法,这就意味着应用程序不需要传输数据到Graphics Card上而得到较高的性能。


一、VAO和VBO创建关联步骤:

 1. Generate Vertex Array Object
 2. Bind Vertex Array Object
 
3. Generate Vertex Buffer Object
4. Bind Vertex Buffer Object
glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object  glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it    glGenBuffers(1, vboID); // Generate our Vertex Buffer Object  glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object  glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW    glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer    glEnableVertexAttribArray(0); // Disable our Vertex Array Object  glBindVertexArray(0); // Disable our Vertex Buffer Object  delete [] vertices; // Delete our vertices from memory


二、绘制步骤:

1.glBindVertexArray
2.glDrawXXX
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object  glDrawArrays(GL_TRIANGLES, 0, 6); // Draw our square  

三、删除:

1.取消绑定
2.删除VBO对象
3.删除VAO对象
glBindVertexArray(0); // Unbind our Vertex Array Object
glDeleteVertexArrays(n, buffers); // 引用的VBO会变成未绑定的,但不会删除VBO数据块
glDeleteBuffers(n, buffers); // 删除VBO缓存区数据块


参考:
http://www.cppblog.com/init/archive/2012/02/21/166098.html
https://www.opengl.org/sdk/docs/man/html/glGenVertexArrays.xhtml
https://www.opengl.org/sdk/docs/man/html/glBindVertexArray.xhtml

#include <stdlib.h>#include <stdio.h>#define GLEW_STATIC#include <GL/glew.h>//#define FREEGLUT_STATIC#include <GL/freeglut.h>#define M_PI 3.1415926#pragma comment(lib, "glew32s.lib")#define BUFFER_OFFSET(offset) ((const GLubyte *) NULL + offset)  #define NumberOf(array) (sizeof(array)/sizeof(array[0]))  typedef struct {GLfloat x, y, z;} vec3;typedef struct {vec3 xlate; /* Translation */GLfloat angle;vec3 axis;} XForm;enum { Cube, Cone, NumVAOs };GLuint VAO[NumVAOs];GLenum PrimType[NumVAOs];GLsizei NumElements[NumVAOs];XForm Xform[NumVAOs] = {{ { -2.0, 0.0, 0.0 }, 0.0,{ 0.0, 1.0, 0.0 } },{ { 0.0, 0.0, 2.0 }, 0.0,{ 1.0, 0.0, 0.0 } }};GLfloat Angle = 0.0;voidinit(){enum { Vertices, Colors, Elements, NumVBOs };GLuint buffers[NumVBOs];// VAO是一个对象,其中包含一个或者更多的Vertex Buffer Objects。而VBO是Graphics Card中的一个内存缓冲区,用来保存顶点信息,颜色信息,法线信息,纹理坐标信息和索引信息等等。//  VAO在Graphics Card线性的存储几个对象信息,替代了以前发送我们需要的数据到Graphics Card上,这也是Direct3D没有立即模式情况下工作的方法,// 这就意味着应用程序不需要传输数据到Graphics Card上而得到较高的性能。// 在缓存区中生成顶点数组对象名字,该名字标记可能不是连续的,但是一定是没有使用的,用顶点数组集合的默认状态来初始化。// generate vertex array object namesglGenVertexArrays(NumVAOs, VAO);{GLfloat cubeVerts[][3] = {{ -1.0, -1.0, -1.0 },{ -1.0, -1.0, 1.0 },{ -1.0, 1.0, -1.0 },{ -1.0, 1.0, 1.0 },{ 1.0, -1.0, -1.0 },{ 1.0, -1.0, 1.0 },{ 1.0, 1.0, -1.0 },{ 1.0, 1.0, 1.0 },};GLfloat cubeColors[][3] = {{ 0.0, 0.0, 0.0 },{ 0.0, 0.0, 1.0 },{ 0.0, 1.0, 0.0 },{ 0.0, 1.0, 1.0 },{ 1.0, 0.0, 0.0 },{ 1.0, 0.0, 1.0 },{ 1.0, 1.0, 0.0 },{ 1.0, 1.0, 1.0 },};GLubyte cubeIndices[] = {0, 1, 3, 2,4, 6, 7, 5,2, 3, 7, 6,0, 4, 5, 1,0, 2, 6, 4,1, 5, 7, 3};// 绑定顶点数组对象名字,当前的顶点数组对象只能激活一个.// glBindVertexArray绑定VAO,一旦VAO绑定后,使glGenBuffers 创建一个Vertex Buffer Object, 当然仍然需要使用glBindBuffer绑定VBO;// 使用glBufferData来初始化和用刚VAO创建的数据分配数据给VBO,再告诉VBO的数据是从VAO而来,需要清理Vertex Attributr Array和Vertex Array Object// bind a vertex array object,// array is the name of a vertex array object previously returned from a call to glGenVertexArrays, // or zero to break the existing vertex array object binding.//  If the bind is successful no change is made to the state of the vertex array object, and any previous vertex array object binding is broken.glBindVertexArray(VAO[Cube]);glGenBuffers(NumVBOs, buffers);// When a buffer object is bound to a target, the previous binding for that target is automatically broken.glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices]);glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVerts),cubeVerts, GL_STATIC_DRAW);// 要清楚关联a buffer object和 a vertex attribute并不发生在glBindBuffer(GL_ARRAY_BUFFER),而是发生在glVertexAttribPointer();当你调用glVertexAttribPointer() ,OpenGL 获取缓冲区绑定到GL_ARRAY_BUFFER 并且关联顶点属性,想象一下GL_ARRAY_BUFFER就像一个全局指针。glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));glEnableClientState(GL_VERTEX_ARRAY);// 前面的GL_ARRAY_BUFFER绑定失效,GL_ARRAY_BUFFER就像一个全局指针glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors]);glBufferData(GL_ARRAY_BUFFER, sizeof(cubeColors),cubeColors, GL_STATIC_DRAW);// 取得当前激活的缓存区对象偏移glColorPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));glEnableClientState(GL_COLOR_ARRAY);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[Elements]);glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);PrimType[Cube] = GL_QUADS;NumElements[Cube] = NumberOf(cubeIndices);}{int i, idx;float dTheta;#define NumConePoints 36  /* We add one more vertex for the cone's apex */GLfloat coneVerts[NumConePoints + 1][3] = {{ 0.0, 0.0, 1.0 }};GLfloat coneColors[NumConePoints + 1][3] = {{ 1.0, 1.0, 1.0 }};GLubyte coneIndices[NumConePoints + 1];dTheta = 2 * M_PI / (NumConePoints - 1);idx = 1;for (i = 0; i < NumConePoints; ++i, ++idx) {float theta = i*dTheta;coneVerts[idx][0] = cos(theta);coneVerts[idx][1] = sin(theta);coneVerts[idx][2] = 0.0;coneColors[idx][0] = cos(theta);coneColors[idx][1] = sin(theta);coneColors[idx][2] = 0.0;coneIndices[idx] = idx;}glBindVertexArray(VAO[Cone]);glGenBuffers(NumVBOs, buffers);glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices]);glBufferData(GL_ARRAY_BUFFER, sizeof(coneVerts),coneVerts, GL_STATIC_DRAW);glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));glEnableClientState(GL_VERTEX_ARRAY);glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors]);glBufferData(GL_ARRAY_BUFFER, sizeof(coneColors),coneColors, GL_STATIC_DRAW);glColorPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));glEnableClientState(GL_COLOR_ARRAY);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[Elements]);glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(coneIndices), coneIndices, GL_STATIC_DRAW);PrimType[Cone] = GL_TRIANGLE_FAN;NumElements[Cone] = NumberOf(coneIndices);}//glEnable(GL_DEPTH_TEST);}void mouse(int button, int state, int x, int y) {switch (button){case GLUT_LEFT_BUTTON:if (state == GLUT_DOWN) {glutIdleFunc(NULL);}break;case GLUT_RIGHT_BUTTON:if (state == GLUT_DOWN) {glutIdleFunc(NULL);}break;default:break;}}void display(){int i;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPushMatrix();glRotatef(Angle, 0.0, 1.0, 0.0);for (i = 0; i < NumVAOs; ++i) {glPushMatrix();glTranslatef(Xform[i].xlate.x, Xform[i].xlate.y,Xform[i].xlate.z);glRotatef(Xform[i].angle, Xform[i].axis.x,Xform[i].axis.y, Xform[i].axis.z);// 激活顶点数组对象,用于设置顶点数组状态,关联到制定的缓存区对象,然后绘制出来glBindVertexArray(VAO[i]);// 当有多个glDrawElements时候,就需要用glBindVertexArray绑定VAO对象,告知绘图函数调用那个顶点数组的索引缓存和顶点缓存glDrawElements(PrimType[i], NumElements[i],GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));glPopMatrix();}glPopMatrix();glutSwapBuffers();}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);glutInitWindowSize(250, 250);glutInitWindowPosition(100, 100);glutInitContextVersion(3, 1);glutCreateWindow("hello");glewInit();init();glutDisplayFunc(display);//glutReshapeFunc(reshape);glutMouseFunc(mouse);//glutMotionFunc(move);//glutKeyboardFunc(keyboardfunc);glutMainLoop();return 0;}


   
0 0