2

在 OpenGL 中我得到了这个(缩短的代码)

void Mesh::CreateBuffer() { 
    glBindBuffer( GL_ARRAY_BUFFER, m_Buffers[POS_VB] );
    glBufferData( GL_ARRAY_BUFFER, sizeof(Positions[0] /*vec3*/) * iVerticeNum, &Positions[0], GL_STATIC_DRAW );
    glEnableVertexAttribArray( POSITION_LOCATION );
    glVertexAttribPointer( POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0 );

    // Fill index buffer.
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_Buffers[INDEX_BUFFER] );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices[0] /*unsigned int*/) * iIndiceNum, &Indices[0], GL_STATIC_DRAW );

}

void Mesh::Render() {

    // bind vertex arrays here!
    .....

    glDrawElements( GL_TRIANGLES, this->NumIndices, GL_UNSIGNED_INT, 0);
    ....
}

上面的代码在我的引擎中运行良好。但是当我决定将它移植到 Metal API 时,我遇到了一些问题——它只使用索引数据渲染模型的一半,它的网格中没有组,它只是简单的网格。但是当我尝试使用顶点数据( drawPrimitives )渲染它时,它渲染得很好。

这是我用来初始化和渲染我的网格的金属代码:

    INIT
    ....
    // Initialize mesh.
    MetalMesh mesh;

    mesh.vertexBuffer = [MetalDataBase->device newBufferWithBytes:Positions/* Vertice data */
                                            length:sizeof(vec3) * iNumVertices
                                           options:MTLResourceOptionCPUCacheModeDefault];
    mesh.indexBuffer = [MetalDataBase->device newBufferWithBytes:Indices
                                           length:sizeof(unsigned int) * iNumIndices
                                          options:MTLResourceOptionCPUCacheModeDefault];

    DRAW
    // Drawing..
    [MetalDataBase->commandEncoder setVertexBuffer:metalResource->metalMeshes[index].vertexBuffer offset:0 atIndex:0];

    // DrawPrimitives renders mesh **fine**, as it should.
    //[MetalDataBase->commandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:iVerticeNum]; 

    // But it doesn't, it just renders half of model,
    // while **iIndiceNum** is right number with its data.
    [MetalDataBase->commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:iIndiceNum indexType:MTLIndexTypeUInt32 indexBuffer:metalResource->metalMeshes[index].indexBuffer indexBufferOffset:0];
4

1 回答 1

4

好的,我已经解决了问题所在。可以在这里找到类似的线程: http ://www.gamedev.net/topic/544669-d3d9-only-1st-submesh-renders-w-indexed-vertexbuffer-solved/

Soo,首先,我使用了几个子网格,在 OpenGL 中我有这样的东西:

    // Count the number of vertices and indices
    for( unsigned int i = 0; i < pScene->mNumMeshes; ++i ) {
        m_Entries[i].MaterialIndex = pScene->mMeshes[i]->mMaterialIndex;
        m_Entries[i].NumIndices    = (pScene->mMeshes[i]->mNumFaces * VerticesPerPrim);
        m_Entries[i].NumVertices   = pScene->mMeshes[i]->mNumVertices;
        m_Entries[i].BaseVertex    = NumVertices;
        m_Entries[i].BaseIndex     = NumIndices;

        Con::Printf( LOG_INFO, "\t\tMesh #%i: %i vertices and %i indices\r\n", i, NumVertices, NumIndices );

        NumVertices += pScene->mMeshes[i]->mNumVertices;
        NumIndices  += m_Entries[i].NumIndices;
    }

    .... load bones, textures etc..

    // Load INDEXIES(haha) data now
    if(something) { ..
        for( unsigned int i = 0; i < paiMesh->mNumFaces; ++i ) {
            const aiFace & Face = paiMesh->mFaces[i];

            //if( Face.mNumIndices == 3 ) {
                Indices[iIndiceNum] = Face.mIndices[0]; ++iIndiceNum;
                Indices[iIndiceNum] = Face.mIndices[1]; ++iIndiceNum;
                Indices[iIndiceNum] = Face.mIndices[2]; ++iIndiceNum;
            //}
        }
     }

但是经过一番愤怒和拉扯之后,我找到了一个我之前发布的链接,它帮助了我(查​​看最后一篇文章)。所以在Metal中我现在有这样的东西:(注意'for'循环第二行中的'+NumVertices' )

    const unsigned int VerticesPerPrim = m_withAdjacencies ? 6 : 3;

    // Count the number of vertices and indices
    for( unsigned int i = 0; i < pScene->mNumMeshes; ++i ) {
        m_Entries[i].MaterialIndex = pScene->mMeshes[i]->mMaterialIndex;
        m_Entries[i].NumIndices    = (pScene->mMeshes[i]->mNumFaces * VerticesPerPrim)  + NumVertices ;
        m_Entries[i].NumVertices   = pScene->mMeshes[i]->mNumVertices;
        m_Entries[i].BaseVertex    = NumVertices;
        m_Entries[i].BaseIndex     = NumIndices;

        g_Console->Print( LOG_INFO, "\t\tMesh #%i: %i vertices and %i indices\r\n", i, NumVertices, NumIndices );

        NumVertices += pScene->mMeshes[i]->mNumVertices;
        NumIndices  += m_Entries[i].NumIndices;
    }


    .. load bones, textures, etc now....

    // Load INDEXIEES data
    if( something ) {
      int offset = 0;

        if( MeshIndex > 0 )
            for ( int k = 0; k < MeshIndex; k++ )
                offset += wtf->mMeshes[k]->mNumVertices;

        for( unsigned int i = 0; i < paiMesh->mNumFaces; ++i ) {
            const aiFace & Face = paiMesh->mFaces[i];

            //if( Face.mNumIndices == 3 ) {
                Indices[iIndiceNum] = Face.mIndices[0] + offset; ++iIndiceNum;
                Indices[iIndiceNum] = Face.mIndices[1] + offset; ++iIndiceNum;
                Indices[iIndiceNum] = Face.mIndices[2] + offset; ++iIndiceNum;
            //}
        }
    }

哈哈,感谢“索引”、“顶点”的语法提示。

这是我使用 Metal 渲染它的方法:

// index = mesh index in Metal API(kinda array)
for( int i = 0; i < mesh[j]->mNumMeshes; ++i ) 
[MetalDataBase->commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:m_Entries[i].numIndices indexType:MTLIndexTypeUInt32 indexBuffer:metalResource->metalMeshes[index].indexBuffer indexBufferOffset:0];

Soo,现在我得到了满载的网格(及其子网格):

是的,这里是

于 2015-06-16T16:19:31.073 回答