天天看點

小白學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原理代碼順序

繼續閱讀