Original Post
Normally I don't post this much code to focus on a problem, but I've been stumped for days on how to use mesh instancing correctly. The few instancing samples I've seen for DirectX have me still wondering how you should set up your vertex data for instance streams so that they are read correctly according to the vertex declaration. I used NVidia's instancing sample because the code looked clearer than other examples I've seen. Well, this is a bare bones version of the code I'm using but I think I stripped it down too far and probably missing some important things. This code compiles without errors but I only see one instance of the mesh, and couldn't use Pix or debugging to help me figure out where I could be missing some function calls. My best guess is that the InstanceData vertex declaration isn't configured correctly. No shader files are being used here. My vertex declarations, and matrix struct used for instancing data: Setup code Rendering code
static D3DVERTEXELEMENT9 vertexN[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
{0, 28, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
const D3DVERTEXELEMENT9 InstanceData[] =
{
{1, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
{1, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
{1, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
{1, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
D3DDECL_END()
};
struct MatrixVertex
{
MatrixVertex(D3DXVECTOR4& i1, D3DXVECTOR4& i2, D3DXVECTOR4&i3, D3DXVECTOR4&i4, D3DXCOLOR&c)
: r1(i1),r2(i2),r3(i3),c1(c) {}
D3DXVECTOR4 r1; // row 1
D3DXVECTOR4 r2; // row 2
D3DXVECTOR4 r3; // row 3
D3DXCOLOR c1; // color
};
D3DXMATRIX* InstanceMatrices;
LPDIRECT3DVERTEXDECLARATION9 pMeshVertexDecl;
LPDIRECT3DVERTEXBUFFER9 MeshVB, ModelMatrixVB;
LPDIRECT3DINDEXBUFFER9 MeshIB;
// Loading the mesh from a file, it produces the set of vertices
// to use in the vertex buffer
TestMesh.loadfromOBJ("Data/test.obj");
// Set up vertex declaration
Display.D3Device()->CreateVertexDeclaration(vertexN, &pMeshVertexDecl);
numInstances = 20;
// Create the matrix vertex buffer
Display.D3Device()->CreateVertexBuffer(numInstances * sizeof(MatrixVertex),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &ModelMatrixVB, NULL);
// Set up the instance matrices
InstanceMatrices = new D3DXMATRIX[numInstances];
// Lock the vertex buffer
MatrixVertex* pVertices;
ModelMatrixVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
for (unsigned i = 0; i < numInstances; i++) {
pVertices.r1 = D3DXVECTOR4(1.0f, 0.0f, 0.0f, (float)i); // translate along X;
pVertices.r2 = D3DXVECTOR4(0.0f, 1.0f, 0.0f, (float)i); // translate along Y;
pVertices.r3 = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 0.0f);
pVertices.c1 = 0xffffffff;
}
ModelMatrixVB->Unlock();
// Set index buffer indices
// Allocating the number of vertices
UINT *g_indices;
g_indices = new UINT[TestMesh.verts().size()];
unsigned totalVertices = TestMesh.verts().size();
for (unsigned i = 0; i < totalVertices; i++) {
g_indices = i;
}
// Create the mesh vertex buffer and index buffer
Display.D3Device()->CreateVertexBuffer(totalVertices * sizeof(vertexN),
D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &MeshVB, NULL );
Display.D3Device()->CreateIndexBuffer(totalVertices * sizeof(UINT),
D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_MANAGED, &MeshIB, NULL);
// Lock the mesh vertex buffer
void *pData;
MeshVB->Lock( 0, 0, (void**)&pData, 0);
memcpy(pData, &(TestMesh.verts().at(0)), totalVertices * sizeof(vertexN));
MeshVB->Unlock();
// Lock the mesh index buffer
MeshIB->Lock(0, 0, (void**)&pData, 0);
memcpy(pData, g_indices, totalVertices * sizeof(UINT));
MeshIB->Unlock();
// Display setup code to start the scene...
// Vertex declaration
Display.D3Device()->SetVertexDeclaration(pMeshVertexDecl);
// stream sources
Display.D3Device()->SetStreamSourceFreq(0,(D3DSTREAMSOURCE_INDEXEDDATA | numInstances));
Display.D3Device()->SetStreamSourceFreq(1,(D3DSTREAMSOURCE_INSTANCEDATA | 1));
Display.D3Device()->SetStreamSource(0, MeshVB, 0,
D3DXGetDeclVertexSize(vertexN, 0));
Display.D3Device()->SetStreamSource(1, ModelMatrixVB, 0,
D3DXGetDeclVertexSize(InstanceData, 1));
// Set index buffer to use
Display.D3Device()->SetIndices(MeshIB);
// Display mesh and clean stream sources
Display.D3Device()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, totalVertices,
0, totalVertices / 3);
Display.D3Device()->SetStreamSourceFreq(0, 1);
Display.D3Device()->SetStreamSourceFreq(1, 1);
Display.D3Device()->EndScene();
Display.D3Device()->Present(0, 0, 0, 0);