本文主要是介绍opengl中VAO和VBO的关系,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
opengl中VAO和VBO的关系
什么是VBO
VBO(vertex buffer object)顶点缓冲对象,用来存储顶点信息,并把这些信息发送给顶点着色器。
VBO是CPU和GPU传递信息的桥梁,**我们把数据存入VBO是在CPU上操作,VBO会自动将数据送至GPU。**送至GPU不需要任何人为操作。关于VBO另外补充解释:使用VBO管理内存(GPU上储存顶点数据),使用VBO好处就是将内存一次性发送大批数据到显卡,而不是每次发送一个顶点数据。从CPU把这些数据发送到显卡相对较慢,所以只要可能就尝试尽量一次性尽可能多的数据。发送到显卡的内存后,顶点着色器几乎能立即访问顶点,过程比较快。
什么是VAO
VBO将顶点数据传送至GPU只是一堆数字,要怎么向GPU解释它们呢,就需要VAO了。有的读者会奇怪,顶点数据无非是一个个三维坐标,三个为一组,传就传了,为什么还需要解释呢?那么我们来看下面这个VBO中的数据:
float vertices[] = {// 位置 // 颜色 //纹理坐标0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f // 右下-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0,0f // 左下0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f 0.0f, 0.0f // 顶部
};`
由以上数据可以看出顶点数据并不是三个为一组的三维坐标,也有两个数字一组的。
如果我们向VBO中传入了以上buffer,并且VBO把它们送入了GPU。
然而,顶点着色器不知道该如何解释这些数字,到底是把它们3个一组,还是先3个一组、后2个一组,或者是3个、2个、3个?
GPU并不知道。这就需要VAO来告诉GPU怎么解释这些缓存数据了,如下:
//vertex coord 顶点坐标属性glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// color attribute 颜色属性glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);// texture coord attribute 纹理坐标属性glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));glEnableVertexAttribArray(2);
上面看似解释了顶点坐标属性、颜色属性、纹理坐标属性三段,其实它们同时绑定在一个VAO中。
总结
VBO是顶点缓冲对象,是CPU和GPU中间的桥梁,开发者只需要将数据存入VBO中,VBO自动将数据送入GPU中。而VBO传输的只是一堆数字,GPU怎么解释这些顶点数据,就需要VAO来解释。
补充
一个VAO可以解释多个VBO,这就涉及到OpenGL的上下文知识:一个完整的OpenGL程序相当于一个容器,我们在用到VAO、VBO时,需要先绑定(Bind操作)、再使用,没有经过绑定的VAO/VBO是不起作用的
绑定VAO,告诉OPenGL用这个VAO来解释这个VBO绑定第一个VBO, 向VBO中写入数据,告知VAO该如何解释VBO
解绑第一个VBO绑定第二个VBO, 向VBO中写入数据,告知VAO该如何解释VBO
解绑第二个VBO
//========================生成VBO,VAO==========================unsigned int VBO[2], VAO;glGenVertexArrays(1, &VAO);glGenBuffers(2, VBO);//=========================绑定VAO===============================glBindVertexArray(VAO);
//===============================================================//=======================绑定第一个VBO============================glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(float), &sphereVertices[0], GL_STATIC_DRAW); //向第一个VBO中写入数据
//===============================================================//================告知VAO该如何解释第一个VBO的信息=================glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);
//===============================================================//=======================解绑第一个VBO===========================glBindBuffer(GL_ARRAY_BUFFER, 0);
//===============================================================//=======================绑定第二个VBO============================glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);glBufferData(GL_ARRAY_BUFFER, sizeof(texVertrices), texVertrices, GL_STATIC_DRAW);//向第二个VBO中写入数据
//===============================================================//================告知VAO该如何解释第二个VBO的信息=================glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);glEnableVertexAttribArray(1);
//=============================================================
好辣,今天就到这里了~
这篇关于opengl中VAO和VBO的关系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!