天天看点

小白学opengl 第五课 之 索引缓冲对象为什么使用EBOEBO原理代码顺序

索引缓冲对象(Element Buffer Objects,EBO)

为什么使用EBO

正常画一个立方体,需要8个顶点,合计6个面

小白学opengl 第五课 之 索引缓冲对象为什么使用EBOEBO原理代码顺序

但实际我们是用了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

小白学opengl 第五课 之 索引缓冲对象为什么使用EBOEBO原理代码顺序