这学期开始了对图形学的学习,打算向这方面努力,加油!!,也是第一次写博客,希望记录自己学习中遇到的问题,对大家也能有所收获,有所错误也请见谅。
VAO与VBO
VAO、VBO的关系,VBO是顶点数据的载体,VAO是顶点数据的解释器。
注:VAO可对应多个VBO,因为顶点属性不只一种,如下图,VAO存储了位置和颜色两种顶点属性解释结果。
VBO:VBO是显存中的一片缓冲区域,用于存放从内存中提交过来的顶点数据。这些数据包括顶点的位置、颜色、纹理坐标等。当GPU进行绘制时,它需要从VBO中读取这些数据,并根据这些数据来渲染图形。VBO的主要作用是减少CPU与GPU之间的数据传输次数,提高渲染效率。
VAO:VAO则是一个用于存储和管理顶点数据状态的对象。它记录了如何解析VBO中的数据,即如何将这些数据映射到着色器中的相应属性上。VAO通过记录glVertexAttribPointer等方法的调用结果,使得在绘制时可以直接通过VAO来访问VBO中的数据,而无需每次绘制时都重新解析VBO。
通过VAO,我们可以避免在每次绘制时都重新解析VBO,从而提高了渲染效率。这是因为VAO存储了顶点数据的解析状态,使得在多次绘制中可以重复使用这些状态。
顶点着色器:
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n" 此处设置了0号顶点属性为位置
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
Opengl学习代码(VAO、VBO、EBO):
//生成VAO,VBO,EBO
unsigned int VBO,VAO,EBO;
//生成顶点数组对象
glGenVertexArrays(1, &VAO);
//生成顶点缓存和元素缓存
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
//先绑定VAO,在VBO之前
glBindVertexArray(VAO);
//把顶点数组复制到缓冲中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//传入索引数据
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 设置0号顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
//启用0号顶点属性指针
glEnableVertexAttribArray(0);
//在顶点数据传输和解释完毕后解绑
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
在OpenGL的学习中,对VBO的处理主要有3个函数(生成->绑定->传入顶点数据):
glGenBuffers(1, &VBO);
1是一个缓冲ID,用Gen生成一个缓冲区。
glBindBuffer(GL_ARRAY_BUFFER, VBO);
此时对VBO进行了绑定,所有输入GL_ARRAY_BUFFER的数据,都会直接被送入现在这个VBO
注:GL_ARRAY_BUFFER是一种顶点缓冲类型
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData将数据从cpu的流中提取出来,放入显存中的VBO管理的区域里。
VAO中的几个函数:
glBindVertexArray(VAO);
绑定VAO,并且要在VBO、EBO之前
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
函数绑定的VBO和顶点属性配置(也就是数据放在哪里,和如何读取数据),0就是0号顶点属性。
glEnableVertexAttribArray和glDisableVertexAttribArray这两个函数用来启用顶点属性,和取消顶点属性链接。
VBO与EBO
EBO(元素缓冲对象)主要作用是与Vertex Buffer Object(顶点缓冲区对象,VBO)配合使用,以缓存图元索引数据,进而提升渲染效率。
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first Triangle
1, 2, 3 // second Triangle
};
如上:避免顶点数据的冗余,包括位置和颜色数据的冗余,6个顶点我们需要使用 6 个 float3 来表示位置和颜色,当需要渲染的顶点数时会造成更大的冗余,我们看看如何针对这个问题来进行优化,事实上我们复用了两个顶点,也就是说其实 4 个顶点数据就够用了。
更详细的内容、实例参考以下内容,讲的很好!!!