OpenGL будет обновлять только последний объект массива вершин - PullRequest
0 голосов
/ 31 октября 2018

Я пишу некоторый код, который генерирует некоторые 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, но я не уверен, что я делаю неправильно.

1 Ответ

0 голосов
/ 31 октября 2018

Связывание объекта Vertex Array не связывает ни один объект буфера массива.
Если вы хотите изменить содержимое буфера массива, вам необходимо связать буфер массива:

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

Если объект массива вершин связан, то именованный объект буфера массива, который связан с точкой привязки, может быть запрошен с помощью glGetVertexAttribIuiv с использованием параметра GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:

например:.

glBindVertexArray(VAO[i]);
GLuint VBO;
glGetVertexAttribIuiv(0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &VBO);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...