LearnOpenGL_Hello Triangle

 

LearnOpenGL_Hello Triangle_第1张图片

 

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);

 结果:

LearnOpenGL_Hello Triangle_第2张图片

 


 修改解绑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);

 结果:

LearnOpenGL_Hello Triangle_第3张图片

在设置指针属性之前解绑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);

结果: 

LearnOpenGL_Hello Triangle_第4张图片

 只要在设置指针属性之前绑定VBO就能正确设置指针。


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

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

 结果:

LearnOpenGL_Hello Triangle_第5张图片

 VAO保存的是在解绑解绑VAO之前,最后的EBO状态,因此,VAO保存的EBO id是0,导致错误。由于VAO不直接存储VBO,在解绑VAO之前,是可以解绑VBO的。

 

 

 

 

你可能感兴趣的:(OpenGL)