LearnOpenGL | VAO VBO EBO
https://learnopengl-cn.github.io/01 Getting started/04 Hello Triangle/
顶点缓冲对象(Vertex Buffer Objects,VBO)
- 顶点缓冲对象VBO是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标,顶点法向量,顶点颜色数据等。在渲染时,可以直接从VBO中取出顶点的各类属性数据,由于VBO在显存而不是在内存中,不需要从CPU传输数据,处理效率更高。
- VBO就是显存中的一个存储区域,可以保持大量的顶点属性信息。
VBO的创建与配置
- 创建VBO的第一步需要开辟(声明/获得)显存空间并分配VBO的ID:
unsigned int VBO;
glGenBuffers(1, &VBO);
- 创建的VBO可用来保存不同类型的顶点数据,创建之后需要通过分配的ID绑定(bind)一下制定的VBO,对于同一类型的顶点数据一次只能绑定一个VBO。
glBindBuffer(GL_ARRAY_BUFFER, VBO); // 绑定VBO
- 接下来调用glBufferData把用户定义的数据传输到当前绑定的显存缓冲区中。
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- 顶点数据传入GPU之后,还需要通知OpenGL如何解释这些顶点数据,这个工作由函数glVertexAttribPointer完成:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
/*
第一个参数指定顶点属性位置,与顶点着色器中layout(location=0)对应。
第二个参数指定顶点的属性size
第三个参数指定数据类型
第四个参数定义是否数据被标准化! [-1,1]
第五个参数为步长 Stride,连续顶点之间属性之间的间隔
第六个参数表示,缓冲区起始位置的偏移量
*/
- 顶点属性glVertexAttribPointer默认是关闭的,使用时要以顶点属性位置值为参数调用glEnableVertexAttribArray开启。
glEnableVertexAttribArray(0);
顶点数组对象(Vertex Arrary Object,VAO)
- VBO保存了一个模型的顶点属性信息,每次绘制模型之前需要绑定顶点的所有信息,当数据量很大时,重复这样的动作变得非常麻烦。VAO可以把这些所有的配置都存储在一个对象中,每次绘制模型时,只需要绑定这个VAO对象就可以了。
- VAO是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的VBO对象的引用。
- VAO本身并没有存储顶点的相关属性数据,这些信息是存储在VBO中的,VAO相当于是对很多个VBO的引用,把一些VBO组合在一起作为一个对象统一管理。
VAO的创建与配置
- 生成一个VAO对象并绑定
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO); // 绑定VAO
- 执行VAO绑定之后其后的所有VBO配置都是这个VAO对象的一部分,可以说VBO是对顶点属性信息的绑定,VAO是对很多个VBO的绑定。
非索引绘图
- OpenGL中所有的图形都是通过分解成三角形的方式进行绘制,glDrawArrays函数负责把模型绘制出来,它使用当前激活的着色器,当前VAO对象中的VBO顶点数据和属性配置来绘制出来基本图形。
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
/*
glDrawArrays (GLenum mode, GLint first, GLsizei count)
第一个参数是绘制的类型
第二个参数是从缓冲中的哪一位开始绘制
第三个是绘制的顶点数量
*/
索引缓冲对象(Element Buffer Object,EBO)
- 索引缓冲对象,和顶点缓存对象一样,也是一个缓存,它专门存储索引,OpenGL调用这些顶点的索引来决定该绘制哪个顶点。
- 索引缓冲对象EBO相当于OpenGL中的顶点数组的概念,是为了解决同一个顶点多洗重复调用的问题,可以减少内存空间浪费,提高执行效率。
- 索引绘制(Indexed Drawing)
- EBO中存储的内容就是顶点位置的索引indices,EBO跟VBO类似,也是在显存中的一块内存缓冲器,只不过EBO保存的是顶点的索引。
EBO的创建与配置
- 创建EBO并绑定,用glBufferData(以GL_ELEMENT_ARRAY_BUFFER为参数)把索引存储到EBO中
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
索引绘图
- 当用EBO绑定顶点索引的方式绘制模型时,需要使用glDrawElements而不是glDrawArrays
glDrawElements(GL_TRIANGLES, izeof(indices)/sizeof(indices[0]), GL_UNSIGNED_INT, 0);
/*
第一个参数指定了要绘制的模式;
第二个参数指定要绘制的顶点个数;
第三个参数是索引的数据类型;
第四个参数是可选的EBO中偏移量设定。
*/