使用单个顶点缓冲区渲染多个三角形

时间:2016-06-19 01:57:25

标签: c++ directx directx-11

以前我为每个网格使用了一个单独的顶点和索引缓冲区,但是我想尝试使用一个大的顶点缓冲区来减少DrawIndexed()调用。假设我有以下数组:

SimpleVertex vertices[] =
{
    { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
    { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
};

WORD indices[] =
{
    3,1,0,
    2,1,3,

    0,5,4,
    1,5,0,

    3,4,7,
    0,4,3,

    1,6,5,
    2,6,1,

    2,7,6,
    3,7,2,

    6,4,5,
    7,4,6,
};

这适用于单个索引多维数据集。但是,如果我想绘制两个立方体怎么办?如何设置索引缓冲区来处理它?我很困惑这些索引是否是每个多维数据集的本地,因此应该重复每36个索引,或者它们是否应该按此递增:

SimpleVertex vertices[] =
{
    //first cube
    { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
    { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
    //second cube
    { XMFLOAT3(-2.0f, 2.0f, -2.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(2.0f, 2.0f, -2.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(2.0f, 2.0f, 2.0f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-2.0f, 2.0f, 2.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
    { XMFLOAT3(-2.0f, -2.0f, -2.0f), XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(2.0f, -2.0f, -2.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(2.0f, -2.0f, 2.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-2.0f, -2.0f, 2.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
};
WORD indices[] =
{
    //First cube
    3,1,0,
    2,1,3,

    0,5,4,
    1,5,0,

    3,4,7,
    0,4,3,

    1,6,5,
    2,6,1,

    2,7,6,
    3,7,2,

    6,4,5,
    7,4,6,

    //second cube
    11,9,8,
    10,9,11,

    8,13,12,
    9,13,8,

    11,12,15,
    8,12,11,

    9,14,13,
    10,14,9,

    10,15,14,
    11,15,10,

    14,12,13,
    15,12,14,
};

基本上,我正在尝试理解如何使用多个对象绘制一个大型索引缓冲区。我是否正确地考虑了这个问题,还是应该让缓冲区一遍又一遍地重复使用相同的索引缓冲区?

我知道使用Instancing,但有时候几何体会发生变化,所以在这种情况下我需要避免使用它。

1 个答案:

答案 0 :(得分:0)

决定开始编写代码来攻击理论盲。事实证明,确实需要增加索引数组以将大型顶点数组视为一个网格。我写了一个函数来为那些感兴趣的人说明这一点:

UINT* VertexCompiler::BuildIndexArray()
{
    UINT* indices;

    int indexCount = 0;

    for (int i = 0; i < (int)mVertexObjects.size(); i++)
        indexCount += mVertexObjects[i].NumIndices;

    mIndexCount = indexCount;

    indices = new UINT[indexCount];

    int numObjects = (int)mVertexObjects.size();
    int index = 0;


    for (int i = 0; i < numObjects; i++)
    {
        for (int j = 0; j < (int)mVertexObjects[i].NumIndices; j++)
        {
            indices[index] = mVertexObjects[i].Indices[j] + (mVertexObjects[i].NumVertices * i);
            index++;
        }

    }

    return indices;
}

确保在完成索引后删除索引指针。通常,在函数内部分配内存并在外部删除它的设计很差,但这仅用于演示目的。通常,您应该在外部分配索引数组,并将其作为指向函数的指针传递。

需要注意的一件重要事情是使用UINT。关于该主题的大多数教科书和文章使用WORD分配较小的索引缓冲区。使用WORD内存分配,递增的索引数组将在索引值65535处溢出。因此,如果您要渲染索引超过16位的大量顶点,请使用UINT并且不要忘记切换到DXGI_FORMAT_R32_UINT而不是DXGI_FORMAT_R16_UINT。

E.g。

IASetIndexBuffer(indicesBuffer, DXGI_FORMAT_R32_UINT, 0);