Перемеженный буфер вершин не отображается правильно

Я нахожусь в процессе написания небольшого кода для загрузки некоторых моделей, в качестве части этого я хочу добавить чередующиеся данные вершин в VBO, однако я заметил странное поведение, когда пытаюсь добавить данные в Vertex Buffer, пара подрешеток не рендерится. Сами вершины и индексы прекрасно работают, когда я использую один VBO для каждого элемента (vvv, tt, nnn). Тем не менее, с чередованным VBO, если я использую трехмерный вектор для std:: vector данных моего VBO, полная сетка будет отображаться правильно (хотя с испорченными текстурами, вероятно, из-за использования трехмерного, а не двухмерного вектора). Чтобы нарисовать сетку, я зацикливаю каждую из подсетей и использую glDrawElementsBaseVertex таким образом:

glDrawElementsBaseVertex(GL_TRIANGLES,
    g_submeshes[i].numIndices,
    GL_UNSIGNED_INT,
    (void*)(sizeof(uint)* g_submeshes[i].baseIndex),
    g_submeshes[i].baseVertex);

Можете ли вы определить, что я сделал не так?

Функция загрузки модели:

void Sprite::InitMesh(uint p_meshIndex,
    const aiMesh* p_mesh,
    vector<aiVector3D>& p_posVec,
    vector<aiVector3D>& p_normVec,
    vector<aiVector2D>& p_uvVec,
    vector<VertexBoneData>& p_bones,
    vector<uint>& p_indices)
{
    const aiVector3D m_zero(0.0f, 0.0f, 0.0f);
    const int m_totalSize = sizeof(aiVector3D)* 2 + sizeof(aiVector2D);

    int m_totalVerts = 0;
    int m_totalIndices = 0;
    for (uint i=0; i < g_scene->mNumMeshes; ++i)
    {
        aiMesh* m_mesh = g_scene->mMeshes[i];
        int m_numFaces = m_mesh->mNumFaces;
        g_matIndices.push_back(m_mesh->mMaterialIndex);
        int m_prevSize = g_vertexBuffer[0].GetCurrentSize();
        g_meshIndices.push_back(m_prevSize / m_totalSize);

        g_submeshes[i].materialIndex = m_mesh->mMaterialIndex;
        g_submeshes[i].numIndices = m_mesh->mNumFaces * 3;
        g_submeshes[i].baseVertex = m_totalVerts;
        g_submeshes[i].baseIndex = m_totalIndices;
        for (unsigned int m = 0; m < m_mesh->mNumVertices; ++m) //Initialise the meshes in the scene
        {
            const aiVector3D* m_pos = &(m_mesh->mVertices[m]);
            const aiVector3D* m_normal = &(m_mesh->mNormals[m]);
            const aiVector3D* m_tex = m_mesh->HasTextureCoords(0) ? &(m_mesh->mTextureCoords[0][m]) : &m_zero;
            p_posVec.push_back(aiVector3D(m_pos->x, m_pos->y, m_pos->z));
            p_normVec.push_back(aiVector3D(m_normal->x, m_normal->y, m_normal->z));
            p_uvVec.push_back(aiVector2D(m_tex->x, m_tex->y));

            g_vertexBuffer[0].AddData(&p_posVec[m], sizeof(p_posVec[m]));
            g_vertexBuffer[0].AddData(&p_uvVec[m], sizeof(p_uvVec[m]));
            g_vertexBuffer[0].AddData(&p_normVec[m], sizeof(p_normVec[m]));
        }

        for (uint j = 0; j < m_numFaces; ++j)
        {
            const aiFace& m_face = m_mesh->mFaces[j];
            assert(m_face.mNumIndices == 3);
            for (uint k = 0; k < 3; ++k)
            {
                p_indices.push_back(m_face.mIndices[k]);
                g_vertexBuffer[1].AddData(&(m_face.mIndices[k]), sizeof(GLuint));
            }
        }
        int m_meshVerts = m_mesh->mNumVertices;
        m_totalVerts += m_meshVerts;
        g_meshSizes.push_back((g_vertexBuffer[0].GetCurrentSize() - m_prevSize) / m_totalSize);
        m_totalIndices += g_submeshes[i].numIndices;

    }
}

Функция AddData:

void VertexBufferObject::AddData(void* p_ptr_data, UINT p_dataSize)
{
    g_data.insert(g_data.end(), static_cast<BYTE*>(p_ptr_data), static_cast<BYTE*>(p_ptr_data) + p_dataSize);
    g_dataSize += p_dataSize;
}

Загрузка в GPU

void Sprite::FinalizeVBO()
{
    glGenVertexArrays(1, &g_VAO);
    glBindVertexArray(g_VAO);

    g_vertexBuffer[0].BindVBO();
    g_vertexBuffer[0].UploadDataToGPU(GL_STATIC_DRAW);  
    glEnableVertexAttribArray(POSITION_LOCATION);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(aiVector3D)+sizeof(aiVector2D), 0);
    // Texture coordinates
    glEnableVertexAttribArray(TEX_COORD_LOCATION);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(aiVector3D)+sizeof(aiVector2D), (void*)sizeof(aiVector3D));
    // Normal vectors
    glEnableVertexAttribArray(NORMAL_LOCATION);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(aiVector3D)+sizeof(aiVector2D), (void*)(sizeof(aiVector3D)+sizeof(aiVector2D)));
    g_vertexBuffer[1].BindVBO(GL_ELEMENT_ARRAY_BUFFER);
    g_vertexBuffer[1].UploadDataToGPU(GL_STATIC_DRAW);
    glBindVertexArray(0);
}

1 ответ

Вы добавляете новые сетки, но используете те же индексы

{
   p_indices.push_back(m_face.mIndices[k]);
   g_vertexBuffer[1].AddData(&(m_face.mIndices[k]), sizeof(GLuint));
}

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

[ V0, V1, V2, V3, V4, V5 ]

И ваш индексный буфер выглядит так:

[ 0, 1, 2, 0, 1, 2 ]

Но вы хотите, чтобы это выглядело так:

[ 0, 1, 2, 3, 4, 5 ]

Это означает, что когда вы добавляете индексы в буфер массива элементов, вы должны увеличивать их на счетчик всех уже увиденных индексов, иначе они будут указывать на предыдущие сетки.

Другие вопросы по тегам