比较常用的时:VBO配合IBO使用。
OpenGL理解VBO,IBO,VAO:https://blog.csdn.net/Mhypnos/article/details/123516615
VBO,VAO和EBO详解:https://www.jianshu.com/p/c7833cd9553a
Opengl:EBO和IBO的使用:https://blog.csdn.net/weixin_44629261/article/details/145257838
VBO:VBO(Vertex Buffer Objects)顶点缓冲区对象,需要绑定缓存类型:GL_ARRAY_BUFFER。 指的是在 GPU 显存里面存储的顶点数据(位置、颜色,纹理等)。仅仅时GPU内存中存放的时顶点各种属性
IBO:(Index Buffer Objects) 顶点索引缓冲区对象,需要绑定缓存类型:GL_ELEMENT_ARRAY_BUFFER。 可以利用点的索引,来构建三角面面片,减少上传GPU中点的数量。使用基于索引的绘图机制。
EBO:Element Buffer Object 元素缓存对象,需要绑定缓存类型:GL_ELEMENT_ARRAY_BUFFER。 于存储顶点索引,避免重复存储相同顶点,减少内存消耗。
VAO:Vertex Array Object 顶点数组对象,就是保存VBO(以及IBO,如果用的话)中的属性配置。
二、void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);
    1、从索引缓冲区渲染模型,即从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取其索引。
    2、mode指定要绘制的图元类型。
    3、count指定要绘制的顶点个数。
    4、type指定索引数据类型。
    5、indices即可以指定EBO的偏移量(使用EBO),也可以传递一个索引数组(不使用EBO,不建议)。
 
总结:VBO,VAO,EBO之间的联系与区别
① 顶点缓冲对象 VBO (VertexBufferOjbect)是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标、顶点法向量、顶点颜色数据等。在渲染时,可以直接从 VBO 中取出顶点的各类属性数据,由于 VBO 在显存而不是在内存中,不需要从CPU传输数据,所以处理效率更高。
所以可以理解为 VBO 就是显存中的一个存储区域,可以保持大量的顶点属性信息。并且可以开辟很多个 VBO ,每个 VBO 在 OpenGL 中有它的唯一标识 ID ,这个 ID 对应着具体的 VBO 的显存地址,通过这个 ID 可以对特定的 VBO 内的数据进行存取操作。
- VBO就像一个仓库,专门存放3D模型所需要的原材料(顶点数据)。所有材料都是提前存放到仓库中的,使用时可以直接取用,无需临时搬运。
- 支持批量数据传输,例如一次性存储万个顶点数据
- 避免每帧将顶点数据从CPU传输到GPU,提升渲染性能
  ② VAO 是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的 VBO 对象的引用,记录GPU如何从与之配对的VBO中读取数据。
   因为 VBO 保存了一个模型的顶点属性信息,每次绘制模型之前需要绑定顶点的所有信息。当数据量很大时,重复这样的动作变得非常麻烦。VAO 可以把这些所有的配置都存储在一个对象中,每次绘制模型时,只需要绑定这个 VAO 对象就可以了。
另外,VAO 本身并没有存储顶点的相关属性数据,这些信息是存储在 VBO 中的,VAO 相当于是对很多个 VBO 的引用,把一些 VBO 组合在一起作为一个对象统一管理。
- 简化顶点属性配置流程,避免每次绘制重复设置
- 绑定VAO后自动恢复关联的VBO和属性配置
- VAO就像一本说明书,告诉工人(GPU)如何从仓库(VBO)中取出材料,并按什么规格(数据类型、偏移量)组装零件(顶点)
 ③ 索引缓冲对象 EBO(Element Buffer Object 索引缓冲对象),  相当于 OpenGL 中的顶点数组的概念,是为了解决同一个顶点多次重复调用的问题,可以减少内存空间浪费,提高执行效率。当需要使用重复的顶点时,通过顶点的位置索引来调用顶点,而不是对重复的顶点信息重复记录,重复调用。
   EBO 中存储的内容就是顶点位置的索引 indices,EBO 跟 VBO 类似,也是在显存中的一块内存缓冲器,只不过 EBO 保存的是顶点的索引。
为什么使用EBO
使用场景:
绘制复杂网格模型,同一顶点会被多个图元共享,用索引来标记每个三角形用到哪个顶点,而不用相同顶点重复创建。
优点
- 节省内存。
- 减少顶点处理次数,提升缓存效效率
没有EBO代码,需要重复保存多个顶点数据:
float vertices[] = {
    // 第一个三角形
    0.0f,  0.5f, 0.0f,
   -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    // 第二个三角形
    0.5f, -0.5f, 0.0f,
    1.0f,  0.0f, 0.0f,
    0.0f,  0.5f, 0.0f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
上面用到的顶点都直接上传GPU了(尽管优点顶点重复使用)。可以很清楚的看到,上面的例子中,两个三角形有一些共用的顶点,但是还是重新写了一遍,就很浪费,所以这时候就要EBO登场了。
-------------------------------------------------------
使用 EBO 的代码
float vertices[] = {
    0.0f,  0.5f, 0.0f,
   -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    1.0f,  0.0f, 0.0f
};
// 用索引来标记每个三角形用到的哪个顶点
unsigned int indices[] = {
    0, 1, 2,
    2, 3, 0
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);//绑定ebo,激活ebo
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//向CPU分配并初始化该ebo的内存
用一个indices的数组指定了每个图元使用的顶点的顺序就好了,这样当在有大量重复顶点的时候,就很省了。
为什么使用VAO()?
VAO ( Vertex Array Object )是OpenGL用来处理顶点数据的一个缓冲区对象,它不能单独使用,都是结合VBO来一起使用的。
当我们使用VBO传入顶点数据时,一般的处理如下: // 绑定VBO,设置VBO中的数据 glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 1. 设置顶点属性 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // 2. 使用Shader程序 glUseProgram(shaderProgram); // 3. 绘制 someOpenGLFunctionThatDrawsOurTriangle();
注意,以上不适用VAO也可以,但是:每次都要如上配置:顶点属性以及激活顶点属性。麻烦:
每当我们绘制一个几何体时,我们需要重复同样的工作(首先绑定缓冲区、然后设置顶点属性)。因为,没有顶点属性的配置,GPU不知道VBO如何使用。
当需要绘制的物体很多时,这个过程就显得有些耗时。那么我们有没有一种方式来简化这一过程呢?这就是VAO做的事情,它将所有顶点绘制过程中的这些设置和绑定过程集中存储在一起,当我们需要时,只需要使用相应的VAO即可。
VAO 本质上是状态记录器,是一种管理 OpenGL 顶点属性配置的对象,用于记录 VBO 和 EBO 的绑定状态及顶点属性设置,避免重复配置。(通俗点的讲,就是VAO只是个指针而已,实际干活的人还是VBO和EBO)
使用场景
- 场景复杂,有多个对象需要渲染时,使用 VAO 可以减少顶点属性配置的复杂度。
- 多次绘制同一个对象,减少状态切换。
优点
1. 减少状态切换。
将所有顶点属性配置打包到一个对象中,后续渲染时只需绑定 VAO 而不是重新配置,避免重复调用 glVertexAttribPointer。
2.简化代码。
管理多个 VBO、EBO,逻辑清晰。
3.提升性能。
减少 OpenGL 状态变更调用的次数。
VAO包含的内容
1. VAO开启或者关闭的状态(glEnableVertexAttribArray和glDisableVertexAttribArray) 2. 使用glVertexAttribPointer对顶点属性进行的设置 3. 存储顶点数据的VBO对象

使用如下:
//创建VAO
GLuint VAO;
glGenVertexArrays(1, &VAO);
//设置当前VAO,之后所有操作(注意:这些操作必须是上文VAO中包含的内容所注明的调用,其他非VAO中存储的内容即使调用了也不会影响VAO)存储在该VAO中
glBindVertexArray(VAO);
   glBindBuffer(GL_ARRAY_BUFFER, VBO); //设置了VBO
   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//设置VBO中的数据
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); //设置顶点属性(索引为0的属性,与shader中的内容有交互)
    glEnableVertexAttribArray(0); //设置开启顶点属性(索引为0的属性,与shader中的内容有交互)
glBindVertexArray(0); //解绑VAO(解绑主要是为了不影响后续VAO的设置,有点类似于C++中指针delete后置空,是个好习惯)
通过上面的代码就完成了对VAO的设置,当我们需要绘制的时候,使用的代码类似于:
场景绘制:
glUseProgram(shaderProgram); glBindVertexArray(VAO); //(再次使用)绑定我们需要的VAO,会导致上面所有VAO保存的设置自动设置完成 someOpenGLFunctionThatDrawsOurTriangle(); glBindVertexArray(0); //解绑VAO
此外,注意不同Opengl版本的API的变化

 
                     
                    
                 
                    
                 
                
 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号