首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Opengl ES之VBO和VAO

前言

本文主要介绍了什么是VBO/VAO,为什么需要使用VBO/VAO以及如何使用VBO和VAO。

VBO

什么是VBO

VBO(vertex Buffer Object):顶点缓冲对象。是在显卡存储空间中开辟的一块区域,在显卡存储空间中开辟一块区域,用于存放顶点的各类属性信息。如顶点坐标、纹理坐标、顶点颜色等数据。在渲染时直接从显VBO去取数据而不必与CPU进行数据交换。

为什么需要使用VBO

将顶点数据保存在内存中,在调用glDrawArrays或者glDrawElements等绘制方法前需要调用相应的方法将数据送入显存,I/O开销大,性能不够好。若采用顶点缓冲区对象存放顶点数据,则不需要在每次绘制前都将顶点数据复制进显存,而是在初始化顶点缓冲区对象时一次性将顶点数据送入显存,每次绘制时直接使用显存中的数据,可以大大提高渲染性能。

如何使用VBO

使用函数和一个缓冲ID生成一个VBO对象:

使用函数绑定顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER

OpenGL有很多缓冲对象类型,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。

使用函数把定义好的顶点数据复制到缓冲的内存中:

是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数。它的第一个参数是目标缓冲的类型,其中VBO代表是的GL_ARRAY_BUFFER。第二个参数指定传输数据的大小(以字节为单位),用一个简单的sizeof计算出顶点数据大小就行。第三个参数是我们希望发送的实际数据。第四个参数指定了我们希望显卡如何管理给定的数据,它有三种形式:

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

GL_DYNAMIC_DRAW:数据会被改变很多。

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

一般情况下位置数据不会改变,每次渲染调用时都保持原样,所以它的使用类型一般是GL_STATIC_DRAW。如果一个缓冲中的数据将频繁被改变,那么使用的类型就是GL_DYNAMIC_DRAW或GL_STREAM_DRAW,这样就能确保显卡把数据放在能够高速写入的内存部分。

用完后使用函数删除缓冲区

我们的目标是灵活使用Opengl绘制一个蓝色的四边形...

普通常规的绘制这里就不多说了,后续可以看代码,或者回顾之前的四边形绘制的文章,这里主要介绍搭配VBO的两种绘制方式:

首先它们使用的顶点着色器和片段着色器都是一样的,都是:

顶点坐标与颜色值坐标分离的方式(数组结构)

先看顶点数据与颜色数据:

VBO数据与绑定:

主要绘制代码:

顶点坐标与颜色值坐标结合的方式(结构数组)

顶点数据与颜色数据混合打乱:

VBO数据绑定:

主要绘制代码:

它们的运行结果都是成功绘制了一个蓝色的四边形:

性能

在上面我们使用了多种不同的组合方式进行了四边形的绘制,其中有将顶点坐标和颜色坐标分离写在两个不同的数组的方式,也有将顶点坐标和颜色坐标组合写在同一个数组,然后使用步长(stride)和偏移量(*pointer)参数控制的方式进行绘制,那么这两种方式那种性能更佳呢?

其中将各种顶点坐标分离在不同数组的写法又成为数组结构,而将各种顶点坐标合并成一个数组的写法又称为结构数组,在《OPENGL ES 3.0编程指南》一书中作者指出,结构数组的写法性能更好。

在大部分情况下,答案是结构数组。原因是,每个顶点的属性数据可以顺序方式读取,这最有可能造成高效的内存访问模式。

VAO

什么是VAO

VAO(vertex Array Object):顶点数组对象。

注意: VAO是OpenGL ES 3.0之后才推出的新特性, 所以在使用VAO前需要确定OpenGL ES的版本是否是3.0之后的版本。

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

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

glEnableVertexAttribArray和glDisableVertexAttribArray的调用。

通过glVertexAttribPointer设置的顶点属性配置。

通过glVertexAttribPointer调用与顶点属性关联的顶点缓冲对象。

在上面VBO的介绍中我们知道每次在绘制的时候都需要频繁地绑定与解绑VBO,每次绘制还需要取出VBO中的数据进行赋值之后才能进行绘制渲染。当数据量大的时候,重复这些操作就会变得很繁琐。通过VAO就可以简化这个过程,因此VAO可以简单理解成VBO的管理者,避免在帧绘制时再去手动操纵VBO,VAO不能单独使用,需要搭配VBO使用。

对于GPU来说VBO就是一堆数据,但是这堆数据怎么解析使用,需要等相关函数在每次绘制的时候告诉GPU,那么VAO的作用就是简化这个过程的,只需要在初始化的时候将这些解析逻辑与VAO绑定一次即可,然后每次在绘制的时候只需绑定对应的VAO,而不必每次再绑定VBO,然后去告诉GPU如何解析相关数据了,可以说是一个性能的优化了。

VAO与VBO经典图

如何使用VAO

首先调用函数生成VAO

调用函数绑定VAO

然后在绘制的时候使用函数使用即可。

退出时通过函数删除VAO

主要绑定代码:

主要使用绘制代码:

下面是完整代码:

VBOVAOOpengl.h

VBOVAOOpengl.cpp

关注我,一起进步,人生不止coding!!!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20220923A0163500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券