阅读 578

OpenGL基础概念理解(1) VAO/VB0/EBO

简介

对于OpenGL而言,一个模型所需要的所有顶点信息(例如:位置,法线,贴图...)都需要放在GPU的显存里,如何高效的管理且有序的管理这些数据便是OpenGL所考虑的问题,了解了OpenGL管理这些数据的方式,我们也就明白了VAO/VBO/EBO三者之间的区别与联系。image.png如图所示,这是在blender中建模的一个模型,由四个顶点构成了两个三角形,将其导出成obj格式后,并且用txt格式打开便可以看到下面的数据。image.png

首先我们来解读下图中的信息:

  • O : 文件名称

  • V : 顶点位置信息

  • Vt:  顶点uv信息

  • Vn:平面法线信息

  • f:平面的顶点构成

对于一些稍微有美术经验的程序员来说,当他打开obj格式文件,模型的大致信息他就一目了然,哪些数据属于顶点位置信息,哪些数据属于顶点的uv信息...可是对于GPU来说,它得到的数据是由一串连续数字组成的长字符,这串字符包含了一个模型的所有数据,它们的杂糅的组织在一起,并且晦涩难懂。

-1.000000 0.000000 1.000000 0.000000 0.065193 1.000000 0.751341 1.000000  1.000000 0.000000.......复制代码

理解了上述概念后,便可以知道OpenGL一系列方法和一组对象具体的功能和作用了,这里先给出一张本人的概念理解图便于大家总体上的理解image.png

  • VBO相当于上述杂乱无章的字符串

  • VAO就相当于GPU能看懂的obj格式,

  • EBO就相当于obj格式中的f规定哪些点规定一个三角形,可以避免顶点的重复设置(比如一个正方形若不引用EBO,则需要六个顶点构成两个三角形,若引入EBO则只需要四个顶点就可以构成两三角形。)

顶点缓冲对象(Vertex Buffer Objects,VBO)

顶点缓冲对象VBO是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标,顶点法向量,顶点颜色数据等。在渲染时,可以直接从VBO中取出顶点的各类属性数据,由于VBO在显存而不是在内存中,不需要从CPU传输数据,处理效率更高。

image.png

VBO的创建与配置

  1. 创建VBO的第一步需要开辟(声明/获得)显存空间并分配VBO的ID:

  2. 把创建的VBO缓冲对象绑定到对应的缓冲类型上。

  3. 将Cpu中的顶点数据传送到该缓冲类型上。

代码如下所示:

unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);复制代码

顶点数组对象(Vertex Arrary Object,VAO)

VBO保存了一个模型的顶点属性信息,每次绘制模型之前需要绑定顶点的所有信息,当数据量很大时,重复这样的动作变得非常麻烦。VAO可以把这些所有的配置都存储在一个对象中,每次绘制模型时,只需要绑定这个VAO对象就可以了。 VAO是一个保存了所有顶点数据属性的状态结合,它对应上一个VBO和一个EBO(如果存在)。VAO中的数据才是顶点着色器中获取数据输入的地方image.png

VAO的创建与配置

  1. 创建VAO的第一步需要开辟(声明/获得)显存空间并分配VAO的ID:

  2. 绑定VAO

  3. 从VBO中获取对应数据到VAO对应的attribute point上面

  4. 启用对应的attribute point

代码如下所示:

unsigned int VAO; 
glGenVertexArrays(1, &VAO);
// ..:: 初始化代码(只运行一次 (除非你的物体频繁改变)) :: .. 
// 1. 绑定VAO
glBindVertexArray(VAO); 
// 2. 把顶点数组复制到缓冲中供OpenGL使用 
glBindBuffer(GL_ARRAY_BUFFER, VBO); 
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
// 3. 设置顶点属性指针 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); 
[...]复制代码

索引缓冲对象(Element Buffer Object,EBO)

索引缓冲对象EBO相当于OpenGL中的顶点数组的概念,是为了解决同一个顶点多洗重复调用的问题,可以减少内存空间浪费,提高执行效率。当需要使用重复的顶点时,通过顶点的位置索引来调用顶点,而不是对重复的顶点信息重复记录,重复调用。image.png

EBO的创建与配置

EBO的创建类似于VBO

  1. 创建EBO的第一步需要开辟(声明/获得)显存空间并分配EBO的ID:

  2. 把创建的EBO缓冲对象绑定到对应的缓冲类型上。

  3. 将Cpu中的顶点索引数据传送到该缓冲类型上。

代码如下所示:

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, 6, GL_UNSIGNED_INT, 0);

重点函数详解

1. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

  • 参数1:填充的缓冲对象类型,里面已经绑定了一个对应的缓冲对象

  • 参数2:填充的数据大小

  • 参数3:填充的数据来源

  • 参数4;显卡如何管理我们的数据


    • GL_STATIC_DRAW :数据不会或几乎不会改变。


    • GL_DYNAMIC_DRAW:数据会被改变很多。


    • GL_STREAM_DRAW :数据每次绘制时都会改变。


2. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void)0);*

  • 参数1:指定我们要配置的顶点属性,与顶点着色器中layout(location=0)对应。

  • 参数2:指定顶点属性的大小。顶点属性是一个vec3,它由3个值组成,所以大小是3。

  • 参数3:指定数据的类型,这里是GL_FLOAT(GLSL中vec*都是由浮点数值组成的)。

  • 参数4:是否希望数据被标准化(Normalize)。如果我们设置为GL_TRUE,所有数据都会被映射到0(对于有符号型signed数据是-1)到1之间。

  • 参数5:指定连续的顶点属性组之间的间隔。它告诉我们在连续的顶点属性组之间的间隔。由于下个组位置数据在3个float之后,我们把步长设置为3 * sizeof(float)

  • 参数6:指定我们的位置数据在缓冲区起始位置的偏移量。


作者:半只小咸鱼
链接:https://juejin.cn/post/7030319769471418381


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐