LearnOpenGL_Hello Triangle

 

 

Vertex Buffer Object(VBO)

一個openGL系統中可以有多個VBO,我們利用VBO來管理顯存,VBO不是存儲空間,一個VBO在顯存中映射一塊用於存儲頂點數據的空間,並使用VBO中存儲的數據來描述和管理這塊空間,因此VBO是對象/結構體。系統中每次只能綁定一個VBO,綁定後就能訪問到這個VBO對應的空間。綁定VBO就相當於在操作系統中更換頁表,保證對存儲空間訪問的獨立性。

Vertex Array Object(VAO)

VAO相當於一個進程控制塊,主要用於保存進程上下文。當我們要切換進程時(更換渲染對象),我們需要切換EBO、頂點屬性指針配置等,爲了將這些切換操作進行封裝,我們將這些需要切換的內容封裝在VAO。於是所有的切換操作簡化爲一次VAO的bind。從VAO綁定到VAO解綁爲止,glVertexAttribPointer、glEnableVertexAttribArray、glEnableVertexAttribArray、glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)、glDisableVertexAttribArray產生作用的結果都會保存在VAO中。

注意:VAO不直接保存綁定的VBO,而是通過glVertexAttribPointer的調用,更新VAO中存儲的指向顯存的指針,及頂點數據存儲的方式(stride)。當調用glVertexAttribPointer時,由於已經處在某個VBO的上下文中,所訪問到的地址必定是當前VBO所對應的地址,直接將這個地址存儲在指針中,不需要另外存儲VBO。可以通過修改代碼驗證VAO的存儲方式。

 

    ///create a vertex buffer obj
    unsigned int VBO;
    glGenBuffers(1, &VBO);
    ///bind the obj to mem
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    ///cp data
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


    ///create a vertex array obj
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    ///進入VAO的上下文   在此之前已進入VBO,使用VBO對應的存儲空間
    glBindVertexArray(VAO);


    ///create a element buffer obj
    unsigned int EBO;
    glGenBuffers(1, &EBO);
    ///綁定EBO 在VAO中記錄EBO 用於下次綁定VAO時,綁定EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    ///設置指針屬性,並保存至VAO,注意此時仍使用之前綁定的VBO,因此指針指向VBO對應的存儲區
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    ///在解綁VAO之前解綁VBO不影響VAO的設置
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

 結果:

 


 修改解綁VBO的時間,如下:

    ///在設置指針屬性之前解綁VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);


    //glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

 結果:

在設置指針屬性之前解綁VBO,導致不能正確的訪問到VBO對應的存儲區,不能爲VAO的指針設置正確的地址,導致出錯。


修改綁定VBO的時間,如下: 

    ///create a vertex buffer obj
    unsigned int VBO;
    glGenBuffers(1, &VBO);
    ///bind the obj to mem
    //glBindBuffer(GL_ARRAY_BUFFER, VBO);
    ///cp data
    //glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


    ///create a vertex array obj
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);




    ///create a element buffer obj
    unsigned int EBO;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);


    ///修改綁定VBO的時間
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);


    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

結果: 

 只要在設置指針屬性之前綁定VBO就能正確設置指針。


在解綁VAO之前解綁EBO,如下:

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    ///解綁EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

 結果:

 VAO保存的是在解綁解綁VAO之前,最後的EBO狀態,因此,VAO保存的EBO id是0,導致錯誤。由於VAO不直接存儲VBO,在解綁VAO之前,是可以解綁VBO的。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章