当前位置: 首页 > 工具软件 > IBO > 使用案例 >

VAO VBO IBO的理解

唐法
2023-12-01

VAO & VBO

 

  • VAO是一个对象,一个VAO可以包含都多个VBO,是一种关联关系
  • 顶点数组对象(Vertex Array Object, VAO)可以像顶点缓冲对象那样被绑定,任何随后的顶点属性调用都会储存在这个VAO中。
  • VBO可以有保存不同的类型,包括顶点坐标、UV、法线、颜色、索引等
  • 通过glBufferData给VBO可以指定相应的类型,再通过glVertexAttribPointer给VBO指定相应的数据格式
  • VBO归根到底是显卡存储空间里的一块缓存区(Buffer)而已

 

VAO 全称 Vertex Array Object,翻译过来叫顶点数组对象,但和Vertex Array(顶点数组)毫无联系!

 

VAO可以像顶点缓冲对象那样被绑定,任何随后的顶点属性调用都会储存在这个VAO中。这样的好处就是,当配置顶点属性指针时,你只需要将那些调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。这使在不同顶点数据和属性配置之间切换变得非常简单,只需要绑定不同的VAO就行了。

 

glBindVertexArray可以设置当前绑定的VAO,然后glGenBuffers生成VBO后,通过glBindBuffer,就将VBO关联到当前的VAO了。VAO里的VBOs都设置好了以后,在绘制的地方只需要设置当前绑定的VAO是哪个,就能按照初始化的VAO来绘制,即调用glDrawArrays。也就是说在初始化的时候,事先确定VAO的格式,在需要的调用的时候,只需要绑定这个特定的VAO就好。

 

glBindVertexArray(0)表示当前不用VAO了,并不是VAO释放了,所以不是你说的那样要一直“bind,unbind,重新Gen”,而是在显存里专门开辟好了这种VAO对应的格式,只需要填数据就好了,而VAO对象是作为一个整体在合适的时候bind。但是看https://stackoverflow.com/questions/25412767/opengl-glbindbuffer0-outside-vao的解释,不需要对vao,vbo unbind,需要用的时候bind就够了。

 

总结VAO、VBO、EBO、纹理

方式

VAO

VBO

EBO

纹理

获取

getGenVertexArrays

getGenBuffers

getGenBuffers

glGenTextures

绑定

glBindBuffer

glBindBuffer

glBindBuffer

glBindTexture

属性定义

glVertexAttribPointer

glVertexAttribPointer

不需要

glTexImage2D

glGenerateMipmap

解绑

glBindVertexArray

glBindBuffer

glBindBuffer

不解绑

使用

glBindVertexArray

glDrawArrays

默认作用于绑定时的顶点

glBindBuffer

glDrawElements

默认使用

删除

glDeleteVertexArrays

glDeleteBuffers

glDeleteBuffers

 

 

当VAO处于活动状态时,不要解除绑定EBO,因为绑定元素缓冲对象存储在VAO中,但是可以解绑VBO,因为调用glvertexattributpointer,已将VBO注册为当前绑定的顶点缓冲区对象,所以可以安全的解除绑定。

 

 

OpenGL的核心模式要求我们使用VAO,所以它知道该如何处理我们的顶点输入。如果我们绑定VAO失败,OpenGL会拒绝绘制任何东西。

 

一个顶点数组对象会储存以下这些内容:

  • glEnableVertexAttribArray和glDisableVertexAttribArray的调用
  • 通过glVertexAttribPointer设置的顶点属性配置
  • 通过glVertexAttribPointer调用与顶点属性关联的顶点缓冲对象

 

IBO(Index Buffer Object)

 

VAO VBO IBO的全称:

  • 顶点数组对象:Vertex Array Object,VAO
  • 顶点缓冲对象:Vertex Buffer Object,VBO
  • 索引缓冲对象:Element Buffer Object,EBO或Index Buffer Object,IBO

 

EBO(比起EBO,我更喜欢用IBO)也是一个缓冲,它专门储存索引,OpenGL调用这些顶点的索引来决定该绘制哪个顶点。绑定EBO, 后用glBufferData把索引复制到缓冲里, 把缓冲的类型定义为GL_ELEMENT_ARRAY_BUFFER, 最后一件要做的事是用glDrawElements来替换glDrawArrays函数,来指明我们从索引缓冲渲染。glDrawElements函数从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取索引。

 

顶点数组对象同样可以保存索引缓冲对象的绑定状态。VAO绑定时正在绑定的索引缓冲对象会被保存为VAO的元素缓冲对象。绑定VAO的同时也会自动绑定EBO。

 

当目标是GL_ELEMENT_ARRAY_BUFFER的时候,VAO会储存glBindBuffer的函数调用。这也意味着它也会储存解绑调用,所以确保你没有在解绑VAO之前解绑索引数组缓冲,否则它就没有这个EBO配置了。

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);


参考:

  • 你好,三角形:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/
  • 如何正确理解 opengl 的 vao ?:https://www.zhihu.com/question/30095978/answer/57755570
  • VAO 与 VBO 的前世今生:https://www.photoneray.com/opengl-vao-vbo/

 

 

 类似资料: