VAO和VBO本文旨在介绍Vao(Vertexarrayobject )和vbo (vertexbufferobject )的相关概念。

随着OpenGL状态和固定管线模式的删除,需要一种将数据传输到图形卡以渲染图形的新方法。 可以采用VBO,也可以采用OpenGL3或更高版本引入的新功能VAO。 可以将同一渲染对象的顶点数据和颜色存储在同一VAO中的不同VBO中。

http://www.Sina.com /是包含一个或多个VBOs的对象,设计用于存储有关完全渲染对象的数据信息,包括渲染对象的顶点信息和每个顶点的颜色信息。

http://www.Sina.com /是显卡的快速显存缓冲区,用于存储顶点信息。

以单色三角形为例,可以使用同一VAO中的两个VBOs分别存储顶点位置和顶点颜色信息。 同样,也可以将法线、纹理或其他信息存储在VBO中。 VAO是一个容器,它总结了可以在glVertexAttribPointer和其他函数中设置的所有状态。 如果使用VAO,则在glVertexAttribPointer调用中指定的状态将保存在当前VAO中。

VAO将对象信息直接存储在图形卡上,而不是根据需要将其传输到图形卡。 这意味着在Direct3D中,OpenGL仅在OpenGL3.X或更高版本中使用。 这意味着APP应用程序不需要将数据传输到图形卡或从图形卡输出数据,从而提高性能。

VAO、VBO的使用方法1.VaO的发生

/* allocateandassignavertexarrayobjecttoourhandle */voidglgenvertexarrays (glsi zein,GLuint *arrays ); n: VAO对象计数,arrays: VAO对象指针2 .绑定vao

/* bindvertexarrayobjectasthecurrentusedobject */voidglbindvertexarray (Glu intarray ); array:生成要绑定的数组的名称VBOs

voidglgenbuffers(glsizein,GLuint* buffers ); n: VBO对象计数,buffers: VBO对象指针4.VBO绑定

voidglbindbuffer(glenumtarget,GLuint buffer; target:GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER,GL_PIXEL_PACK_BUFFER,orgl _ pixel _ n pack _ n pack

voidglbufferdata(glenumtarget,GLsizeiptr size,const GLvoid * data,GLenum usage ); target: GL_ARRAY_BUFFER (表示顶点数据)、GL_ELEMENT_ARRAY_BUFFER (表示索引数据)、 GL_PIXEL_PACK_BUFFER )表示从OpenGL传递给OpenGL的像素数据的or GL_PIXEL_UNPACK_BUFFER,size:缓冲器对象的字节数data usage: 6.指定必须启用的顶点属性数组的索引

/* enableattributeindexasbeingused */voidglenablevertexattribarray (Glu intindex ); index:指定了必须启用的顶点属性数组的索引7。 将数据分配给相应的顶点属性数组

voidglvertexattribpointer (Glu intindex,GLint size,GLenum type,GLboolean normalized,const GLvoid * pointer ); 索引:数据存储库的VBO下标size:数据量type:数据类型normalized:是否需要对指向数组中第一个顶点属性的第一数据的pointer:进行归一化8 .呈现时对应的pointer:

lbindvertexarray(VaoHandle ); 9 .清除使用过的绑定

glbindvertexarray(0; 需要注意的是,glenablevertexattribarray (index )和glvertexattribpointer (index,…)的索引参数是指attribute index和shader

]。

实例

下面代码绘制一个三角形。

// Include standard headers#include <stdio.h>#include <stdlib.h>#include <unistd.h>// Include GLEW#include <GL/glew.h>// Include GLFW#include <GLFW/glfw3.h>GLFWwindow* window;// Include GLM#include <glm/glm.hpp>using namespace glm;#include <common/shader.hpp>int main( void ){ // Initialise GLFW if( !glfwInit() ) { fprintf( stderr, “Failed to initialize GLFW\n” ); getchar(); return -1; } glfwWindowHint(GLFW_SAMPLES, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Open a window and create its OpenGL context window = glfwCreateWindow( 1024, 768, “Tutorial 02 – Red triangle”, NULL, NULL); if( window == NULL ){ fprintf( stderr, “Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n” ); getchar(); glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // Initialize GLEW glewExperimental = true; // Needed for core profile if (glewInit() != GLEW_OK) { fprintf(stderr, “Failed to initialize GLEW\n”); getchar(); glfwTerminate(); return -1; } // Ensure we can capture the escape key being pressed below glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); // Dark blue background glClearColor(0.0f, 0.0f, 0.4f, 0.0f); // Create and compile our GLSL program from the shaders GLuint programID = LoadShaders( “SimpleVertexShader.vertexshader”, “SimpleFragmentShader.fragmentshader” ); static const GLfloat g_vertex_buffer_data[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; GLuint VertexArrayID; // ①产生vao glGenVertexArrays(1, &VertexArrayID); // ②绑定vao glBindVertexArray(VertexArrayID); GLuint vertexbuffer; // ③产生vbo glGenBuffers(1, &vertexbuffer); // ④绑定vbo glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // ⑤给vbo分配数据 glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); // ⑥给对应顶点属性数组指定数据 glVertexAttribPointer( 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. 3, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); do{ // Clear the screen glClear( GL_COLOR_BUFFER_BIT ); // Use our shader glUseProgram(programID); // ⑦渲染时绑定对应的VAO glBindVertexArray(VertexArrayID); // 1rst attribute buffer : vertices // ⑧使用下标对应的属性信息 Enable attribute index 0 as being used glEnableVertexAttribArray(0); // Draw the triangle ! glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle glDisableVertexAttribArray(0); // Swap buffers glfwSwapBuffers(window); glfwPollEvents(); } // Check if the ESC key was pressed or the window was closed while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 ); // Cleanup VBO glDeleteBuffers(1, &vertexbuffer); glDeleteVertexArrays(1, &VertexArrayID); glDeleteProgram(programID); // Close OpenGL window and terminate GLFW glfwTerminate(); return 0;}

参考文章:
[1].http://www.cppblog.com/init/archive/2012/02/21/166098.html
[2].https://blog.csdn.net/xiajun07061225/article/details/7628146
[3].https://blog.csdn.net/danshiming/article/details/56286880
[4].https://www.xuebuyuan.com/2127857.html
[5].https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)
[6].https://gamedev.stackexchange.com/questions/147718/what-are-layout-qualifier-in-glsl-used-for