该原创文章首发于微信公众号:字节流动

VBO 和 EBO

VBO(Vertex Buffer Object)是指顶点缓冲区对象,而 EBO(Element Buffer Object)是指图元索引缓冲区对象,VAO 和 EBO 实际上是对同一类 Buffer 按照用途的不同称呼

OpenGLES2.0 编程中,用于绘制的顶点数组数据首先保存在 CPU 内存,在调用 glDrawArrays 或者 glDrawElements 等进行绘制时,需要将顶点数组数据从 CPU 内存拷贝到显存。

但是很多时候我们没必要每次绘制的时候都去进行内存拷贝,如果可以在显存中缓存这些数据,就可以在很大程度上降低内存拷贝带来的开销。

OpenGLES3.0 VBO 和 EBO 的出现就是为了解决这个问题。 VBO 和 EBO 的作用是在显存中提前开辟好一块内存,用于缓存顶点数据或者图元索引数据,从而避免每次绘制时的 CPU 与 GPU 之间的内存拷贝,可以提升渲染性能,降低内存带宽和功耗

OpenGLES3.0 支持两类缓冲区对象:顶点数组缓冲区对象、图元索引缓冲区对象。GL_ARRAY_BUFFER 标志指定的缓冲区对象用于保存顶点数组,GL_ELEMENT_ARRAY_BUFFER 标志指定的缓存区对象用于保存图元索引

VBO(EBO)的创建和更新。

// 创建 2 个 VBO(EBO 实际上跟 VBO 一样,只是按照用途的另一种称呼)
glGenBuffers(2, m_VboIds);// 绑定第一个 VBO,拷贝顶点数组到显存
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 绑定第二个 VBO(EBO),拷贝图元索引数据到显存
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

GL_STATIC_DRAW 标志标识缓冲区对象数据被修改一次,使用多次,用于绘制。

本例中顶点着色器和片段着色器增加 color 属性:

//顶点着色器
#version 300 es
layout(location = 0) in vec4 a_position;   // 位置变量的属性位置值为 0
layout(location = 1) in vec3 a_color;      // 颜色变量的属性位置值为 1
out vec3 v_color;                          // 向片段着色器输出一个颜色
void main()
{                                          v_color = a_color;                     gl_Position = a_position;
};//片段着色器
#version 300 es
precision mediump float;
in vec3 v_color;
out vec4 o_fragColor;
void main()
{o_fragColor = vec4(v_color, 1.0);
}

顶点数组数据和图元索引数据:

// 4 vertices, with(x,y,z) ,(r, g, b, a) per-vertex
GLfloat vertices[] ={-0.5f,  0.5f, 0.0f,       // v01.0f,  0.0f, 0.0f,        // c0-0.5f, -0.5f, 0.0f,       // v10.0f,  1.0f, 0.0f,        // c10.5f, -0.5f, 0.0f,        // v20.0f,  0.0f, 1.0f,        // c20.5f,  0.5f, 0.0f,        // v30.5f,  1.0f, 1.0f,        // c3};
// Index buffer data
GLushort indices[6] = { 0, 1, 2, 0, 2, 3};

VBO更新后内存中的数据结构

由于顶点位置和颜色数据在同一个数组里,一起更新到 VBO 里面,所以需要知道 2 个属性的步长和偏移量。

为获得数据队列中下一个属性值(比如位置向量的下个 3 维分量)我们必须向右移动 6 个 float ,其中 3 个是位置值,另外 3 个是颜色值,那么步长就是 6 乘以 float 的字节数(= 24 字节)。

同样,也需要指定顶点位置属性和颜色属性在 VBO 内存中的偏移量。对于每个顶点来说,位置顶点属性在前,所以它的偏移量是 0 。而颜色属性紧随位置数据之后,所以偏移量就是 3 * sizeof(GLfloat) ,用字节来计算就是 12 字节。

使用 VBO 和 EBO 进行绘制。

glUseProgram(m_ProgramObj);//不使用 VBO 的绘制
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (3+3)*sizeof(GLfloat), vertices);glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, (3+3)*sizeof(GLfloat), (vertices + 3));glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);//使用 VBO 的绘制
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (3+3)*sizeof(GLfloat), (const void *)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, (3+3)*sizeof(GLfloat), (const void *)(3 *sizeof(GLfloat)));glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[1]);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);

VAO

VAO(Vertex Array Object)是指顶点数组对象,VAO 的主要作用是用于管理 VBO 或 EBO ,减少 glBindBuffer 、glEnableVertexAttribArray、 glVertexAttribPointer 这些调用操作,高效地实现在顶点数组配置之间切换


VAO 与 VBO 之间的关系

基于上小节的例子创建 VAO :

// 创建并绑定 VAO
glGenVertexArrays(1, &m_VaoId);
glBindVertexArray(m_VaoId);// 在绑定 VAO 之后,操作 VBO ,当前 VAO 会记录 VBO 的操作
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (3+3)*sizeof(GLfloat), (const void *)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, (3+3)*sizeof(GLfloat), (const void *)(3 *sizeof(GLfloat)));glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[1]);glBindVertexArray(GL_NONE);

使用 VAO 进行绘制:

// 是不是精简了很多?
glUseProgram(m_ProgramObj);glBindVertexArray(m_VaoId);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);

联系与交流

技术交流、获取源码可以扫码添加我的微信:Byte-Flow ,领取视频教程

NDK OpenGL ES 3.0 开发(四):VBO、EBO 和 VAO相关推荐

  1. NDK OpenGL ES 3.0 开发(一):绘制一个三角形

    该原创文章首发于微信公众号:字节流动 什么是 OpenGLES OpenGLES 全称 OpenGL for Embedded Systems ,是三维图形应用程序接口 OpenGL 的子集,本质上是 ...

  2. NDK OpenGL ES 3.0 开发(二十):3D 模型

    该原创文章首发于微信公众号:字节流动 OpenGLES 3D 模型 OpenGLES 3D 模型本质上是由一系列三角形在 3D 空间(OpenGL 坐标系)中构建而成,另外还包含了用于描述三角形表面的 ...

  3. NDK OpenGL ES 3.0 开发(七):Transform Feedback

    该原创文章首发于微信公众号:字节流动 什么是 Transform Feedback Transform Feedback(变换反馈)是在 OpenGLES3.0 渲染管线中,顶点处理阶段结束之后,图元 ...

  4. NDK OpenGL ES 3.0 开发(二十二):PBO

    该原创文章首发于微信公众号:字节流动 PBO 是什么 OpenGL PBO(Pixel Buffer Object),被称为像素缓冲区对象,主要被用于异步像素传输操作.PBO 仅用于执行像素传输,不连 ...

  5. NDK OpenGL ES 3.0 开发(八):坐标系统

    该原创文章首发于微信公众号:字节流动 OpenGL 坐标系统 我们知道 OpenGL 坐标系中每个顶点的 x,y,z 坐标都应该在 -1.0 到 1.0 之间,超出这个坐标范围的顶点都将不可见. 将一 ...

  6. NDK OpenGL ES 3.0 开发(十七):相机基础滤镜

    该原创文章首发于微信公众号:字节流动 相机基础滤镜 上文中我们通过 ImageReader 获取到 Camera2 预览的 YUV 数据,然后利用 OpenGLES 渲染实现相机预览,这一节将利用 G ...

  7. win7下搭建opengl es 2.0开发环境

    原文  http://codingnow.cn/opengles/1501.html 主题 OpenGL ES Windows 7 1. 下载AMD的OpenGL ES2.0的模拟器 ,下载地址:  ...

  8. OpenGL ES 3.0 开发(三):YUV 渲染

    该原创文章首发于微信公众号:字节流动 YUV 渲染原理 前面文章一文掌握 YUV 图像的基本处理介绍了 YUV 常用的基本格式,本文以实现 NV21/NV12 的渲染为例. 前文提到,YUV 图不能直 ...

  9. 《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》一第6章 让场景更逼真——光照效果...

    本节书摘来异步社区<OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例>一书中的第6章,第6.1节,作者: 吴亚峰 责编: 张涛,更多章节内容可以访问云栖社区"异步社 ...

最新文章

  1. Linux ssh命令无法使用
  2. java.lang.AbstractMethodError: com.mysql.jdbc.PreparedStatement.setCharacterStream(ILjava/io/Reader;
  3. JavaScript为什么使用原型模式而不是类模式
  4. Spring 事情具体详尽的解释
  5. C++——auto_ptr类
  6. SparseArrayE详解
  7. Web设计与开发终极资源大全
  8. 基于JAVA+SpringMVC+Mybatis+MYSQL的高校勤工助学管理系统
  9. SSH框架和Redis的整合(1)
  10. 介绍如何隐藏JDataGridBean的SplashScreen?
  11. 【特征提取】基于matlab熵函数语音端点检测【含Matlab源码 1764期】
  12. mysql索引的方法_mysql索引类型和索引方法
  13. canon lbp6200 macos下单面双面打印设置
  14. html 英文发音,一些英文字母的发音
  15. Scala使用ALS模型做推荐
  16. sai绘制羽毛写字教程
  17. 谷歌整体战略:关于人工智能、云服务和登月计划的未来
  18. Bluedroid 函数分析:BTA_GATTC_Open
  19. speedoffice使用方法-word怎么快速分页呢
  20. js中isFinite

热门文章

  1. 氚云标准版的简单讲解
  2. [转](45)中断门和快速调用进0环详解,重写 WriteProcessMemory
  3. 微信web开发者工具使用教程
  4. java获取json数组格式中的值
  5. 什么是OpenJDK?
  6. OpenJDK能替代Oracle JDK 吗
  7. mediumtext_【紧急求助】关于mediumtext类型数据的调用
  8. lip Studio Paint EX 2.0.3 CSP漫画绘图设计
  9. 电脑删除一些流氓软件/病毒
  10. CMake Error: Could not create named generator Visual Studio 17 2022 win32