【问题标题】:Interleaved Vertex buffer does not render correctly交错顶点缓冲区无法正确渲染
【发布时间】:2014-10-01 06:28:23
【问题描述】:

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

【问题讨论】:

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


    【解决方案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 ]
    

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

    【讨论】:

    • 这件事发生在我不久前,但我试图让它工作失败了,所以我想它一定是别的东西。从那以后我发现这是因为我使用 'aiProcess_JoinIdenticalVertices' 标志调用我的 Assimp::Importer::Readfile(),这自然不适用于 1-n 索引数组。有趣的是,为了提高效率,是否有任何明显的方法可以以保持使用此标志的方式计算索引?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 2015-05-17
    相关资源
    最近更新 更多