为什么此顶点缓冲区对象无法更新

Why does this vertex buffer object fails to Update?

本文关键字:更新 对象 缓冲区 顶点 为什么      更新时间:2023-10-16

我有以下几段代码,其中我成功地创建了一个顶点缓冲区对象,用数据初始化它,并使用GLSL 4.0渲染它。但是,当我在动画后更新存储在顶点中的数据时,OpenGL会给我错误代码0x502,并且不接受我更新的顶点信息。

有人能告诉我为什么这些代码不允许我的顶点信息成功更新吗?我还应该提到,有时,成功更新的数据并不总是一致/可预测的。

使用的数据结构

    struct Vertex3{
        glm::vec3       vtx;        //0
        glm::vec3       norm;       //3
        glm::vec3       tex;        //6 Use for texturing or color
    };
vector<Vertex3> geometry.vertices3;

初始化代码

    void solidus::Mesh::initVBO(){
        geometry.totalVertexCount = geometry.getVertexCount();
        // Allocate an OpenGL vertex array object.
        glGenVertexArrays(1, &vertexArrayId);
        glGenBuffers(2,geometry.vboObjects);
        // Bind the vertex array object to store all the buffers and vertex attributes we create here.
        glBindVertexArray(vertexArrayId);
        glBindBuffer(GL_ARRAY_BUFFER, geometry.vboObjects[VERTEX_DATA]);
        //size the size of the total vtx
        GLuint byte_size = getTotalSize();

        //Reserve the inital space for the vertex data
        glBufferData(GL_ARRAY_BUFFER, byte_size, NULL, GL_STREAM_DRAW);

        if(geometry.isStructVertex4())
            initVBO4( );
        else if(geometry.isStructVertex3())
            initVBO3( );
        else
            initVBO2( );

        //release
        glBindVertexArray(0);

        geometry.vertices4.clear();
        //geometry.vertices3.clear();
        geometry.vertices2.clear();
    }
void solidus::Mesh::initVBO3( ){
    //getTotalSize() ==  getVtxCount() * sizeof(Vertex3);
    glBufferSubData(GL_ARRAY_BUFFER, 0, getTotalSize(), &geometry.vertices3[0]);
        //Note: offsetof -- c++ standard library
        //Note: glVertexAttribPointer- first parameter is location of GLSL variable
        glEnableVertexAttribArray(0);  // Vertex4 position
        glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,vtx) );
        // Vertex4 normal
        glEnableVertexAttribArray(1);
        glVertexAttribPointer( (GLuint)1, 3, GL_FLOAT, GL_TRUE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,norm)  );
        // Texture coords
        glEnableVertexAttribArray(2);
        glVertexAttribPointer( (GLuint)2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3),(GLvoid*)offsetof(Vertex3,tex) );
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry.vboObjects[INDEX_DATA]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*geometry.indices.size(), &geometry.indices[0], GL_STATIC_DRAW);
}

更新网格顶点信息为什么失败

void solidus::Mesh::uploadVertexGLFx(){

    glBindBuffer(GL_ARRAY_BUFFER, geometry.vboObjects[VERTEX_DATA]);

    string e0="";
    if(geometry.isStructVertex2()){
        solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices2[0]);
        e0="Vertex2";
    }else if(geometry.isStructVertex3()){
        //THIS IS THE POINT OF INTEREST: at least suspected!!!!!
        //  getVtxCount() * sizeof(Vertex3) = getTotalSize
        glBufferSubData(GL_ARRAY_BUFFER, 0, getTotalSize (), &geometry.vertices3[0]);
        e0="Vertex3";
    }else {
        solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices4[0]);
        e0="Vertex4";
    }
    //report error is glGetError is not equal to 0
    postMsg("failed to upload vertex for struct " + e0 , "uploadVertexGLFx",30);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

我将updateVertexGLFx函数修改为下面列出的代码。与这种好的主要区别在于,在我将顶点信息重新提供给GL后,我使用GL*AtribPointer通知OpenGL指针偏移。现在,当我调用更新函数时,程序会可靠地更新。

void solidus::Mesh::uploadVertexGLFx(){

    glBindBuffer(GL_ARRAY_BUFFER, geometry.vboObjects[VERTEX_DATA]);

    string e0="";
    if(geometry.isStructVertex2()){
        solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices2[0]);
        e0="Vertex2";
    }else if(geometry.isStructVertex3()){
        //glBufferData(GL_ARRAY_BUFFER, getTotalSize (), NULL, GL_STREAM_DRAW);
        //THIS IS THE POINT OF INTEREST: at least suspected!!!!!
        //  getVtxCount() * sizeof(Vertex3) = getTotalSize
        cout << "Total Size = " << getTotalSize() <<endl;
        cout << "Vtx Count = " << getVtxCount() << endl;
        cout << "Sizeof(Vertex3)=" <<sizeof(Vertex3)<<endl;
        Vertex3 *f = new Vertex3[getVtxCount()];
        for(int i=0; i<getVtxCount();i++){
            f[i] = geometry.vertices3[i];
        }

        glBufferData(GL_ARRAY_BUFFER, getTotalSize(), NULL, GL_STREAM_DRAW);
        glBufferSubData(GL_ARRAY_BUFFER, 0, getTotalSize (), f);

        //Note: glVertexAttribPointer- first parameter is location of GLSL variable
        glEnableVertexAttribArray(0);  // Vertex4 position
        glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,vtx) );
        // Vertex4 normal
        glEnableVertexAttribArray(1);
        glVertexAttribPointer( (GLuint)1, 3, GL_FLOAT, GL_TRUE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,norm)  );
        // Texture coords
        glEnableVertexAttribArray(2);
        glVertexAttribPointer( (GLuint)2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3),(GLvoid*)offsetof(Vertex3,tex) );
        delete f;
        f = nullptr;
        e0="Vertex3";
    }else {
        solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices4[0]);
        e0="Vertex4";
    }
    //report error is glGetError is not equal to 0
    postMsg("failed to upload vertex for struct " + e0 , "uploadVertexGLFx",30);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}