前言
本文主要介绍了什么是VBO/VAO,为什么需要使用VBO/VAO以及如何使用VBO和VAO。
VBO
什么是VBO
VBO(vertex Buffer Object):顶点缓冲对象。是在显卡存储空间中开辟的一块区域,在显卡存储空间中开辟一块区域,用于存放顶点的各类属性信息。如顶点坐标、纹理坐标、顶点颜色等数据。
在渲染时直接从显VBO去取数据而不必与CPU进行数据交换。
为什么需要使用VBO
将顶点数据保存在内存中,在调用glDrawArrays或者glDrawElements等绘制方法前需要调用相应的方法将数据送入显存,I/O开销大,性能不够好。
若采用顶点缓冲区对象存放顶点数据,则不需要在每次绘制前都将顶点数据复制进显存,而是在初始化顶点缓冲区对象时一次性将顶点数据送入显存,
每次绘制时直接使用显存中的数据,可以大大提高渲染性能。
如何使用VBO
- 使用函数
glGenBuffers
和一个缓冲ID生成一个VBO对象:
unsigned int VBO;
glGenBuffers(1, &VBO);
- 使用函数
glBindBuffer
绑定顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER
OpenGL有很多缓冲对象类型,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。
glBindBuffer(GL_ARRAY_BUFFER, VBO);
- 使用函数
glBufferData
把定义好的顶点数据复制到缓冲的内存中:
// vertices表示顶点数组
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData
是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数。它的第一个参数是目标缓冲的类型,其中VBO代表是的GL_ARRAY_BUFFER。第二个参数指定传输数据的大小(以字节为单位),用一个简单的sizeof计算出顶点数据大小就行。
第三个参数是我们希望发送的实际数据。第四个参数指定了我们希望显卡如何管理给定的数据,它有三种形式:
GL_STATIC_DRAW :数据不会或几乎不会改变。
GL_DYNAMIC_DRAW:数据会被改变很多。
GL_STREAM_DRAW :数据每次绘制时都会改变。
一般情况下位置数据不会改变,每次渲染调用时都保持原样,所以它的使用类型一般是GL_STATIC_DRAW。如果一个缓冲中的数据将频繁被改变,那么使用的类型就是GL_DYNAMIC_DRAW或GL_STREAM_DRAW,这样就能确保显卡把数据放在能够高速写入的内存部分。
- 用完后使用函数
glDeleteBuffers
删除缓冲区
今天我们以之前绘制四边形的实践为例子,使用VBO的方式来实现四边形的绘制:Opengl ES之四边形绘制
我们的目标是灵活使用Opengl绘制一个蓝色的四边形…
普通常规的绘制这里就不多说了,后续可以看代码,或者回顾之前的四边形绘制的文章,这里主要介绍搭配VBO的两种绘制方式:
首先它们使用的顶点着色器和片段着色器都是一样的,都是:
// 顶点着色器
static const char *ver = "#version 300 es\n"
"in vec4 aColor;\n"
"in vec4 aPosition;\n"
"out vec4 vColor;\n"
"void main() {\n"
" vColor = aColor;\n"
" gl_Position = aPosition;\n"
"}";
// 片元着色器
static const char *fragment = "#version 300 es\n"
"precision mediump float;\n"
"in vec4 vColor;\n"
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vColor;\n"
"}";
- 顶点坐标与颜色值坐标分离的方式(数组结构)
先看顶点数据与颜色数据:
// 使用绘制两个三角形组成一个矩形的形式(三角形带)
// 第一第二第三个点组成一个三角形,第二第三第四个点组成一个三角形
const static GLfloat VERTICES[] = {
0.5f,-0.5f, // 右下
0.5f,0.5f, // 右上
-0.5f,-0.5f, // 左下
-0.5f,0.5f, // 左上
};
// vbo颜色
const static GLfloat COLOR_ICES[] = {
0.0f,0.0f,1.0f,1.0f,
0.0f,0.0f,1.0f,1.0f,
0.0f