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);
//=============================================================

好辣,今天就到这里了~

你可能感兴趣的:(c++,笔记)