交错的顶点缓冲区无法正确渲染

时间:2014-08-07 21:09:40

标签: c++ opengl vector casting vertex-buffer

我正在编写一些代码来加载一些模型,作为其中的一部分,我想将交错的顶点数据添加到VBO中,但是当我发现时我注意到了一些奇怪的行为尝试将数据添加到顶点缓冲区,几个子网格不会渲染。当我为每个元素(vvv,tt,nnn)使用单个VBO时,顶点和索引本身非常精细。然而,使用交错的VBO,如果我使用3D矢量作为我的VBO的std :: vector数据,则完整网格将正确绘制(尽管纹理搞砸了,可能是使用3D而不是2D矢量)。为了绘制网格,我循环每个子网格并使用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 个答案:

答案 0 :(得分:0)

您正在添加新网格,但使用相同的索引

{
   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 ]

这意味着当您将索引添加到元素数组缓冲区时,您必须通过计数已经看到的所有索引来递增它们,否则它们将指向先前的网格。