OpenGL将只更新最后一个顶点数组对象

0qx6xfy6  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(173)

我正在写一些代码,生成一些 VAO ,然后当物理已经更新时,进行调用以更新VAO内的顶点,然后进行调用以重绘这些对象。
我的代码的问题是UpdateScene只更新了最后一个 VAO 。

void BuildBuffers(std::vector<demolish::Object>& objects)
{
    VAO = new UINT[objects.size()];
    glGenVertexArrays(objects.size(),VAO);
    int counter = 0;
    for(auto& o:objects)
    {
        if(o.getIsSphere())
        {
            BuildSphereBuffer(o.getRad(),o.getLocation(),counter);
            counter++;
        }
        else
        {
        }
    }
}

void BuildSphereBuffer(float radius,std::array<iREAL,3> position,int counter)
{

    GeometryGenerator::MeshData meshObj;
    geoGenObjects.push_back(meshObj);
    geoGen.CreateSphere(radius,30,30,meshObj,position);

    VAOIndexCounts.push_back(meshObj.Indices.size());
    glGenBuffers(2,BUFFERS);
    glBindVertexArray(VAO[counter]);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER,BUFFERS[0]);
    glBufferData(GL_ARRAY_BUFFER,
                                  meshObj.Vertices.size()*sizeof(GLfloat)*11,
                                  &meshObj.Vertices.front(), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BUFFERS[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                                   meshObj.Indices.size() * sizeof(UINT),
                                   &meshObj.Indices.front(), GL_STATIC_DRAW);

    glVertexPointer(3, GL_FLOAT,sizeof(GLfloat)*11, 0);
    glNormalPointer(GL_FLOAT,sizeof(GLfloat)*11,(GLvoid*)(3*sizeof(GLfloat)));
}

然后,下面的函数在被调用时更新缓冲区。

void UpdateScene(float dt, std::vector<demolish::Object>& objects)
{
    float x = radius*sinf(phi)*cosf(theta);
    float z = radius*sinf(phi)*sinf(theta);
    float y = radius*cosf(phi);

    AV4FLOAT position(x,y,z,1.0);

    AV4FLOAT target(0.0,0.0,0.0,0.0);
    AV4FLOAT up(0.0,1.0,0.0,0.0);

    viewModelMatrix = formViewModelMatrix(position,target,up);

    for(int i=0;i<objects.size();i++)
    {
        geoGen.CreateSphere(objects[i].getRad(),
                            30,
                            30,
                            geoGenObjects[i],
                            objects[i].getLocation());

        VAOIndexCounts[i] = geoGenObjects[i].Indices.size();

        glBindVertexArray(VAO[i]);
        glBufferSubData(GL_ARRAY_BUFFER,
                                0,
                                geoGenObjects[i].Vertices.size()*sizeof(GLfloat)*11,
                                &geoGenObjects[i].Vertices.front());
    }

    RedrawTheWindow();

}

这段代码的问题是它没有更新所有的缓冲区,只更新了“最后一个”缓冲区。例如,如果对象的大小为3,那么即使所有三个对象的位置都改变了,也只更新了最后一个缓冲区的顶点。
我已经把范围缩小到OpenGL,但我不确定我做错了什么。

nqwrtyyt

nqwrtyyt1#

绑定顶点数组对象不会绑定任何数组缓冲区对象。
如果你想改变数组缓冲区的内容,那么你必须绑定数组缓冲区:

GLuint VBO = .....; // VBO which corresponds to VAO[i]

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(
    GL_ARRAY_BUFFER, 0,
    geoGenObjects[i].Vertices.size()*sizeof(GLfloat)*11,
    &geoGenObjects[i].Vertices.front());

注意,一个顶点数组对象可能会引用不同的数组缓冲区对象,对于每个属性。那么应该绑定哪一个呢?
从OpenGL 4.5开始,您也可以通过直接状态访问版本来执行此操作。
请参阅glNamedBufferSubData

glNamedBufferSubData (
    VBO, 0,
    geoGenObjects[i].Vertices.size()*sizeof(GLfloat)*11,
    &geoGenObjects[i].Vertices.front());

如果顶点数组对象是绑定的,则可以使用参数GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING通过glGetVertexAttribIuiv查询绑定到绑定点的命名数组缓冲区对象:
例如:

glBindVertexArray(VAO[i]);
GLuint VBO;
glGetVertexAttribIuiv(0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &VBO);

相关问题