【HarmonyOS实战开发】鸿蒙OpenGL使用VBO、EBO、VAO提升渲染性能

一、VBO

VBO是顶点缓冲对象,顶点缓冲对象在GPU中存储数据,加速渲染过程。

1、1 VBO优点
  • 减少数据从CPU到GPU的传输,提升渲染效率。在鸿蒙OpenGL入门,绘制三角形中介绍了绘制三角形,其实当时绘制的三角形性能并不高。三角形的顶点数据和颜色数据都是从CPU获取,如果图形复杂,数据每次都从CPU拷贝到GPU,性能就太低。更好的方式是一次性将全部数据从CPU拷贝到GPU,之后需要数据的时候,直接从GPU中获取数据。在GPU中设置一个对象,这个对象就是VBO,一次性将全部数据拷贝到VBO中。VBO在GPU中,从VBO中获取数据就是从GPU中获取数据,大大的提升了渲染性能。
  • 数据保存在GPU,可重复使用。
  • 可以在GPU中转换数据,减少CPU负载。
1、2 使用VBO基本步骤

需要注意的是,下面的操作需要在链接完程序后调用,也就是在调用完glLinkProgram函数后。

  • 调用glGenBuffers函数生成VBO对象。

void GL_APIENTRY glGenBuffers (GLsizei n, // 一次生成多少个VBO
GLuint *buffers); // VBO对象的索引值
  • 调用glBindBuffer进行绑定。
void GL_APIENTRY glBindBuffer (GLenum target, // 目标数据类型,它是个常量,GL_ARRAY_BUFFER表示用于存储顶点数据
GLuint buffer); // VBO对象的id,解绑时需要将该参数设置为0
  • 调用glBufferData将顶点数据复制到VBO对象中。
void GL_APIENTRY glBufferData (GLenum target, // 目标数据类型,它是个常量,GL_ARRAY_BUFFER表示用于存储顶点数据
GLsizeiptr size, // 拷贝数据的大小 
const void *data, // 从哪拷贝数据
GLenum usage); // 常量,指定拷贝数据的方式,一般设置为GL_STATIC_DRAW,表明是一次性拷贝
  • 调用glVertexAttribPointer从VBO中读取数据,glVertexAttribPointer函数之前文章介绍过,当使用VBO的时候,需要将glVertexAttribPointer函数最后一个参数设置为0。
  • 解绑VBO对象,VBO是在GPU分配空间,当不需要时,主动释放空间。
glDeleteBuffers(VBO_COUNT, vboIds);

如下代码是使用VBO的流程。

bool VBOTriangleExample::init() {
 if (TriangleExample::init()) {
 // 生成vbo对象
 glGenBuffers(1, vboIds);
 // 绑定vbo
 glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]);
 // 将顶点数据复制到VBO对象
 glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
 // 解绑vbo
 glBindBuffer(GL_ARRAY_BUFFER, 0);
 return true;
 }
 return false;
}
1、3修改绘制代码

有三处改动

  • 调用glBindBuffer函数告知着色器从哪个vbo中读取数据。
  • 调用glVertexAttribPointer的时候,需要将最后一个参数设置为0,表示从GPU读取数据。
  • 调用glBindBuffer函数,最后一个参数设置为0,表示解绑vbo。

void VBOTriangleExample::draw() {
 glUseProgram(program);
 // 告知着色器从哪个vbo中读
### Android 平台上 OpenGLVBOEBOVAO 的用法 #### 一、VBO (Vertex Buffer Object) VBO 是用于存储大量顶点数据的对象。通过将顶点数据上传至 GPU 显存中,可以显著提高渲染效率。 ```java // 创建并绑定一个VBO int vbo; vbo = GLES20.glGenBuffers(); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo); FloatBuffer vertexBuffer = ... // 初始化顶点缓冲区 GLES20.glBufferData( GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * Float.BYTES, vertexBuffer, GLES20.GL_STATIC_DRAW ); ``` 此代码片段展示了如何创建和初始化一个 VBO 来保存顶点坐标[^1]。 #### 二、EBO (Element Buffer Object 或 Index Buffer) EBO 存储的是索引列表,用来定义哪些顶点应该被连接起来形成几何图形。这有助于减少重复顶点的数量,从而节省内存空间并加快绘制速度。 ```java // 创建并填充EBO int ebo; ebo = GLES20.glGenBuffers(); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ebo); ShortBuffer indexBuffer = ... // 初始化索引缓冲区 GLES20.glBufferData( GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Short.BYTES, indexBuffer, GLES20.GL_STATIC_DRAW ); ``` 上述代码说明了怎样构建 EBO 及其关联的数据结构。 #### 三、VAO (Vertex Array Object) VAO 负责管理多个 VBOs 和它们之间的配置关系。它记录了每个属性指针的位置以及相应的格式信息,使得切换不同类型的顶点布局变得简单快捷。 ```java // 设置VAO状态 int vao; vao = GLES20.glGenVertexArrays(); GLES20.glBindVertexArray(vao); // 配置顶点属性指针 GLES20.glEnableVertexAttribArray(0); // 启用第一个属性列 GLES20.glVertexAttribPointer( 0, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, offset ); // 解绑当前VAO GLES20.glBindVertexArray(0); ``` 这段程序描述了如何建立一个新的 VAO 实例,并对其进行必要的参数设定[^3]。 当准备实际绘图时: ```java // 绑定先前设置好的VAO GLES20.glBindVertexArray(vao); // 执行绘制命令 if(ebo != null){ GLES20.glDrawElements(primitiveType, count, type, indicesOffset); }else{ GLES20.glDrawArrays(primitiveType, firstIndex, count); } // 清理工作 GLES20.glBindVertexArray(0); ``` 以上就是针对 Android 设备上使用 OpenGL ES 进行三维图形编程时涉及到的三个重要概念及其具体实现方法[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值