0 Replies - 479 Views - Last Post: 20 April 2015 - 07:40 PM Rate Topic: -----

#1 BBeck   User is offline

  • Here to help.
  • member icon

Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Multiple Meshes in a Single Vertex Buffer in DirectX

Posted 20 April 2015 - 07:40 PM

So, I've basically covered this before in a post I made in the XNA forum about half a year ago. In fact, reading that helped remind me of what is going on here.

I realized that you can store multiple meshes in a single vertex buffer, but almost none of the DX examples or tutorials out there cover this. So, I've pointed out how to do it in XNA. Now I just figured out how to do it in DirectX 11 and wanted to share.

One example where you might want multiple meshes in a single vertex buffer is if you have a model with sub-meshes. Let's say you have a model of a car and you made the car body separate from the wheels, doors, and hood so that you could animate them. They are completely separate meshes that you basically always want to draw together.

In your modeling program, you join them to the car body in a parent-child relationship which allows them to be animated separately.

You could, I suppose, have a completely separate vertex buffer for each part. It would largely work the same. But it just makes a lot of sense to me to put the entire car in one vertex buffer. And if you're making a model class, you may not know how many sub-meshes the model will have. And so you would have a variable number of vertex buffers that could be theoretically infinite. And you would have to manage them as an array of vertex buffers or something to keep them together.

On the other hand, you allocate the size of the vertex buffer at runtime; so, having an unknown number of sub-meshes will always fit in the buffer until your graphics card runs out of memory. It's just a lot easier to manage the whole car as a single buffer.

Anyway, here's some pseudo-code

  SCENEOBJECTVERTEX TriangleVertexList[3] =
    {XMFLOAT3(0.0f, 0.5f, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)},
    {XMFLOAT3(0.45f, -0.5, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f)},
    {XMFLOAT3(-0.45f, -0.5f, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f)},

    {XMFLOAT3(0.0f, 0.5f, 5.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)},
    {XMFLOAT3(0.45f, -0.5, 5.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f)},
    {XMFLOAT3(-0.45f, -0.5f, 5.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f)}
  unsigned int TriangleIndexList[3] = {0, 1, 2, 0, 1, 2};

  UINT Stride = sizeof(VERTEX);
  GraphicsDeviceContext->IASetVertexBuffers(0, 1, &VertexBuffer, &Stride, 0);
  GraphicsDeviceContext->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
  GraphicsDeviceContext->DrawIndexed(IndicesInThismeshPart, FirstIndexInBuffer, FirstVertexInBuffer);	

So, here I've defined 6 vertices for a vertex buffer. It's two identical multicolor triangle 5 units apart on the Z axis, but the two separate meshes could be completely 100% different including a different number of vertices in each one. The only thing that must be the same is that they must all share the same vertex type/structure.

Notice that my index list starts over at zero for the second mesh. This is probably the most confusing thing of the entire works because it appears that nothing is pointing to the second triangle. Each sub-mesh has it's own set of indicies in the index buffer.

So, to draw the second triangle IndicesInThismeshPart=3, FirstIndexInBuffer=3 (assuming it's counting from 0 instead of 1), and FirstVertexInBuffer=3. IndicesInThismeshPart is the number of indices from the index buffer that make up the sub-mesh. FirstIndexInBuffer is the element number in the index buffer where the first index is for the sub-mesh. So, in this example, that's the position of the second zero in the index buffer as an unsigned int. Then FirstVertexInBuffer is the position of the first vertex of the sub-mesh in the vertex buffer. That's why each sub-mesh starts its indexing over again at 0, because the vertex offset will get added to every index of that sub mesh.

So, it will look in the index buffer at the 4th position (FirstIndexInBuffer - numbering from zero) and see the index value is zero. Then it will go to the 4th vertex (FirstVertexInBuffer - again counting from zero) and add the zero value to it to get the first vertex used. The next index is 1 and so it would add 1 to the first vertex position and get the next vertex.

Notice that I did not use the offsets in IASetVertexBuffers or IASetIndexBuffers. Those seem to offset the same way FirstVertexInBuffer and FirstIndexInBuffer do. So, it's redundant and if you don't zero them out you'll be pointing to the wrong spots in the buffers.

Notice also that you would not have to re-set the buffers again and could immediately make a DrawIndexed() call to draw the first triangle after changing the values of FirstVertexInBuffer and FirstIndexInBuffer.

It's fairly simple once you figure out how it works, but I haven't found a book or a tutorial anywhere that covers this and it's something you may want to use pretty quick when you start getting into DX11.

This post has been edited by BBeck: 20 April 2015 - 07:51 PM

Is This A Good Question/Topic? 0
  • +

Page 1 of 1