索引缓冲对象(Element Buffer Objects,EBO)
为什么使用EBO
正常画一个立方体,需要8个顶点,合计6个面
但实际我们是用了4*6=24个点来画的,因为4个点组成一个面,我们能看出来,有很多重复点,为了能节省内存空间,我们想只用8个点描画立方体,这需要用到EBO
VertexData vc[] = {
//正面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
//右面
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
//左面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
{QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f)}, //8
{QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
//背面
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f)}, //8
//顶面
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
//底面
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f)}, //8
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
};
EBO原理
//顶点有8个
VertexData vcs[] = {
//正面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f)}, //8
};
//索引 对应8个面,每个面说明使用哪4个顶点
GLuint indices[] = { // 起始于0!
0, 1, 2, 3, // face 1
1, 4, 5, 2, // face 2
0, 7, 6, 3, // face 3
4, 5, 6, 7, // face 4
2, 5, 6, 3, // face 5
1, 4, 7, 0, // face 6
};
代码顺序
创建
//1 使用glGenBuffers函数生成一个缓冲ID
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
绑定VAO
//2 绑定vao
glBindVertexArray(VAO);
绑定VBO,EBO
//3 使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER缓冲类型上
glBindBuffer(GL_ARRAY_BUFFER, VBO); //(绑定和解绑的顺序很重要,勿更改)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
复制数据
//4 把用户定的义数据复制到当前绑定缓冲的函数
glBufferData(GL_ARRAY_BUFFER, sizeof(vcs), vcs, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
链接属性
//5 链接顶点属性
//indx: 属性名
//size: 顶点大小
//type: 数据类型
//normalized:数据被标准化
//stride: 步长
//ptr: 数据在缓冲中起始位置的偏移量
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)sizeof(QVector3D));
解绑 VBO
//6 解绑缓存着色器(绑定和解绑的顺序很重要,勿更改)
glBindBuffer(GL_ARRAY_BUFFER, 0);
解绑VAO
//7 解绑VAO
glBindVertexArray(0);
PS: 这里我颠倒了顺序,并没有出现问题,可能qt给优化过,不解绑也没事,另外EBO不用解绑,就算要解绑,也要在VAO解绑后
绘制过程
绑定vao
//1 绑定vao
glBindVertexArray(VAO);
开启属性
//2 开启顶点属性
glEnableVertexAttribArray(0);
//颜色值
glEnableVertexAttribArray(1);
绘制四边形
//3 绘制四边形
//24个索引值
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, (GLvoid*)0);
停用属性
//4 停用对应的顶点属性数组
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
解绑VAO
//5 解绑VAO
glBindVertexArray(0);
源代码
https://gitee.com/chen227/opengl_OpenGLFunctions5