This tutorial is part of a Collection: 01. DirectX 9 - Braynzar Soft Tutorials
2540
views
07. Index Buffers
Index Buffers are used to speed up or optimize your program. They are pretty much the same thing as Vertex Buffers, but instead of storing vertices, it stores indeces. Buffers are used to speed up the rendering of geometry, and can be placed in video memory.
I probably should have covered Index Buffers in with the Vertex Buffers, but oh well. Index Buffers are used the same way as Vertex Buffers. They both speed up the rendering of geometry by placing a block of data into video memory. The IDirect3DIndexBuffer9 interface is used to represent the Index Buffer. Index Buffers speed up your program by eliminating duplicate vertices. When your storing vertices in the Vertex Buffer, you only have to store each one once. They don't make much of a difference in this program, but when your working with more complex models, multiple triangles might use the same vertice, making you have to define it more than once when your filling your Vertex Buffer. The first thing we'll do is declare two Index Buffers, one for the triangle and one for the square. IDirect3DIndexBuffer9* TriangleIndexBuffer = 0; IDirect3DIndexBuffer9* SquareIndexBuffer = 0; Index Buffers are created by the following method: HRESULT IDirect3DDevice9::CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle **Length **- Number of bytes we want to allocate to the index buffer. If we wanted to allocate memory for 3 indeces, we would say this 3 * sizeof(WORD). **Usage **- Additional Properties of how the buffer will be used. **Format **- Size of the Indices. Use D3DFMT_INDEX16 for 16-bit indices or D3DFMT_INDEX32 for 32-bit indices. Not all devices support 32-bit indices. **Pool **- Memory pool that buffer is placed in. **ppIndexBuffer **- Pointer to created Index Buffer. **pSharedHandle **- Will not be used here. So set it to zero. d3dDevice->CreateIndexBuffer( 3 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &TriangleIndexBuffer, 0); d3dDevice->CreateIndexBuffer( 6 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &SquareIndexBuffer, 0); Accessing the Index Buffers memory is done the same way as the Vertex Buffer. First we lock the buffer, then place our data in it, then lock it back up. This is where you will see how to use the Index Buffer. Using an Index Buffer lets you create the triangles out of the data in the Vertex Buffer. Three indices are needed for each triangle. WORD* indices = 0; TriangleIndexBuffer->Lock(0, 0, (void**)&indices, 0); indices[0] = 0; indices[1] = 1; indices[2] = 2; TriangleIndexBuffer->Unlock(); SquareIndexBuffer->Lock(0, 0, (void**)&indices, 0); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 2; indices[4] = 1; indices[5] = 3; SquareIndexBuffer->Unlock(); Now in the CleanUpScene() function, we need to release our Allocated Index Buffer memory. We do this with the following lines. TriangleIndexBuffer->Release(); SquareIndexBuffer->Release(); Easy as that. We go to the RenderScene() function now and set the Index Buffer for each primitive. d3dDevice->SetIndices(TriangleIndexBuffer); ... ... d3dDevice->SetIndices(SquareIndexBuffer); To draw our indexed primitives, we need to use the DrawIndexedPrimitive method. HRESULT IDirect3DDevice9::DrawIndexedPrimitive( D3DPRIMITIVETYPE Type, INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount ); **Type **- Type of Primitive **BaseVertexIndex **- Sometimes you might want to group multiple objects indices together in one Index Buffer. BaseVertexIndex is the start of that primitives indices. **MinIndex **- Minimum index value that will be referenced. **NumVertices **- Number of Vertices that will be used. **StartIndex **- Starting point to begin reading indices. **PrimitiveCount **- Number of primitives to draw. d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 3, 0, 1); ... ... d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2); thats's it! If you run your program, you will see nothing changed. Thats because indices are more used for more complex objects and meshes. I just wanted to get this out of the way so we could get on to more interesting things! Here's the final code: main.cpp ... ... IDirect3DIndexBuffer9* TriangleIndexBuffer = 0; IDirect3DIndexBuffer9* SquareIndexBuffer = 0; ... ... bool SetupScene(){ //Set up our Scene ... ... d3dDevice->CreateIndexBuffer( //Create a new index buffer 3 * sizeof(WORD), //Size of the index buffer D3DUSAGE_WRITEONLY, //Access Instructions D3DFMT_INDEX16, //Format of Indices, 16 or 32 bits D3DPOOL_MANAGED, //How to manage memory &TriangleIndexBuffer, //Pointer to store data in 0); d3dDevice->CreateIndexBuffer( 6 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &SquareIndexBuffer, 0); ... ... WORD* indices = 0; //Lock TriangleIndexBuffer TriangleIndexBuffer->Lock(0, 0, (void**)&indices, 0); indices[0] = 0; indices[1] = 1; indices[2] = 2; //Define the triangle TriangleIndexBuffer->Unlock(); //Unlock TrianglIndexBuffer //Lock SquareIndexBuffer SquareIndexBuffer->Lock(0, 0, (void**)&indices, 0); indices[0] = 0; indices[1] = 1; indices[2] = 2; //First triangle of square indices[3] = 2; indices[4] = 1; indices[5] = 3; //Second triangle of square SquareIndexBuffer->Unlock(); //Unlock SquareIndexBuffer ... ... } void CleanUpScene(){ //Release memory TriangleVertexBuffer->Release(); SquareVertexBuffer->Release(); TriangleIndexBuffer->Release(); SquareIndexBuffer->Release(); return; } bool RenderScene(float timeDelta) //Renders a single frame { ... ... d3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000055, 1.0f, 0); d3dDevice->BeginScene(); //Start drawing our scene if(displaytriangle == true){ //Defines the source and start of the triangle data d3dDevice->SetStreamSource(0, TriangleVertexBuffer, 0, sizeof(Vertex)); //Sets indices for triangle d3dDevice->SetIndices(TriangleIndexBuffer); //Set the flexible vertex format d3dDevice->SetFVF(VertexFVF); //draw the indexed polygon d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 3, 0, 1); } if(displaysquare == true){ d3dDevice->SetStreamSource(0, SquareVertexBuffer, 0, sizeof(Vertex)); d3dDevice->SetIndices(SquareIndexBuffer); d3dDevice->SetFVF(VertexFVF); d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2); } d3dDevice->EndScene(); //Stop drawing our scene d3dDevice->Present(0, 0, 0, 0); //Display our newly created scene ... ... }
Sign in to comment