/*索引缓存的好处:

 (1).减少了顶点缓存的顶点个数(不需重复顶点)。
 (2).灵活修改图形形状(通过修改索引序列而不是顶点序列)。

 (3).提高渲染效率,runtime将多次用到的顶点数据放置在相近的地方Cache中(local reference)。*/

1.创建顶点缓存

Device->CreateIndexBuffer(
         36 * sizeof(WORD), // 索引缓存的字节数,个数是三角形的个数*3,索引缓存个数还是没有减少的。 

         D3DUSAGE_WRITEONLY, // 使用类型为只读类型,获取指针然后写入数据,数据将会批量提交 

         D3DFMT_INDEX16, // D3DFMT_INDEX16是16bit,D3DFMT_INDEX32是32bit 

         D3DPOOL_MANAGED, // D3DPOOL类型,创建在SM中,需要时候拷贝到AGP内存/显存中

        &IB,


      

0);//保留
    Device->CreateVertexBuffer(
         8 * sizeof(Vertex), 
         D3DUSAGE_WRITEONLY,
         Vertex::FVF,
         D3DPOOL_MANAGED,
         &VB,
         0);

2.填充索引缓存

3.设置索引缓存数据到流

// define unique vertices:
     Vertex* vertices;
     VB->Lock(0, 0, (void**)&vertices, 0);

     // vertices of a unit cube   // 如果没有索引缓存,那么每个面需要2个三角形,每个三角形需要3个顶点,一个面6个顶点,6个面36个顶点。
   // 用了索引,那么只需要8个顶点就可以了,这样索引每个三角形需要3个,一共需要36个索引点。
// DX中三角形顺时针(左手定则)为正面, 逆时针为背面会被消隐,OGL则相反。
// 索引缓存点的个数是三角形片面数 * 3得到的个数。
 // 所有索引缓存表面从外往物体里看都是顺时针给出的(例如六面体背面的索引缓存顺序),索引缓存每连续三个为一个三角形即可。
   vertices[0] = Vertex(-1.0f, -1.0f, -1.0f);
     vertices[1] = Vertex(-1.0f,  1.0f, -1.0f);
     vertices[2] = Vertex( 1.0f,  1.0f, -1.0f);
     vertices[3] = Vertex( 1.0f, -1.0f, -1.0f);
     vertices[4] = Vertex(-1.0f, -1.0f,  1.0f);
     vertices[5] = Vertex(-1.0f,  1.0f,  1.0f);
     vertices[6] = Vertex( 1.0f,  1.0f,  1.0f);
     vertices[7] = Vertex( 1.0f, -1.0f,  1.0f);

     VB->Unlock();
     WORD* indices = 0; 

     IB->Lock(0, 0, (void**)&indices, 0); 

    // DX中三角形顺时针(左手定则)为正面, 逆时针为背面会被消隐;OGL则相反。
 
    // 索引缓存的三角形顺序都是顺时针的(平视该三角形)。 

     // front side 

     indices[0]  = 0; indices[1]  = 1; indices[2]  = 2; 

     indices[3]  = 0; indices[4]  = 2; indices[5]  = 3; 


     // back side 

     indices[6]  = 4; indices[7]  = 6; indices[8]  = 5; 

     indices[9]  = 4; indices[10] = 7; indices[11] = 6; 


     // left side 

     indices[12] = 4; indices[13] = 5; indices[14] = 1; 

     indices[15] = 4; indices[16] = 1; indices[17] = 0; 


     // right side 

     indices[18] = 3; indices[19] = 2; indices[20] = 6; 

     indices[21] = 3; indices[22] = 6; indices[23] = 7; 


     // top 

     indices[24] = 1; indices[25] = 5; indices[26] = 6; 

     indices[27] = 1; indices[28] = 6; indices[29] = 2; 


     // bottom 

     indices[30] = 4; indices[31] = 0; indices[32] = 3; 

     indices[33] = 4; indices[34] = 3; indices[35] = 7; 


    IB->Unlock();
Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
Device->SetIndices(IB);Device->SetFVF(Vertex::FVF);

4.渲染到表面缓存

// Draw cube.
  Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
HRESULT DrawIndexedPrimitive(
  [in]  D3DPRIMITIVETYPE Type, // 图元的类型,不能使用D3DPT_POINTLIST
  [in]  INT BaseVertexIndex, // 顶点缓存的第一个顶点索引的偏移位置,偏移是因为当多个顶点缓存合并成一块全局缓存中时每块都有一个基准的offset值。
  [in]  UINT MinIndex, // 顶点缓存开始渲染的最小值
  [in]  UINT NumVertices, // 顶点的个数,第一个是 BaseVertexIndex + MinIndex
  [in]  UINT StartIndex, // 索引缓存开始的位置
  [in]  UINT PrimitiveCount // 图元的个数
);



实例片段,解释如何指定顶点的个数和索引的个数:

//
 // 
 // File: cube.cpp
 // 
 // Author: Frank Luna (C) All Rights Reserved
 //
 // System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 
 //
 // Desc: Provides an interface to create and render a cube.
 //          
 //

 #include "cube.h"
 #include "vertex.h"

 Cube::Cube(IDirect3DDevice9* device)
 {
     // save a ptr to the device
     _device = device;// 因为启用了顶点法向量和纹理坐标,不能只用8个顶点,一个面有2个三角形中有2个顶点可以共享,所以是4个顶点,6个面24个顶点。
     _device->CreateVertexBuffer(
         24 * sizeof(Vertex), 
         D3DUSAGE_WRITEONLY,
         FVF_VERTEX,
         D3DPOOL_MANAGED,
         &_vb,
         0);

     Vertex* v;
     _vb->Lock(0, 0, (void**)&v, 0);

     // build box

     // fill in the front face vertex data
     v[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
     v[1] = Vertex(-1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
     v[2] = Vertex( 1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);
     v[3] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);

     // fill in the back face vertex data
     v[4] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
     v[5] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f);
     v[6] = Vertex( 1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
     v[7] = Vertex(-1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f);

     // fill in the top face vertex data
     v[8]  = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
     v[9]  = Vertex(-1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
     v[10] = Vertex( 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);
     v[11] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);

     // fill in the bottom face vertex data
     v[12] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f);
     v[13] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f);
     v[14] = Vertex( 1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f);
     v[15] = Vertex(-1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);

     // fill in the left face vertex data
     v[16] = Vertex(-1.0f, -1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
     v[17] = Vertex(-1.0f,  1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
     v[18] = Vertex(-1.0f,  1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
     v[19] = Vertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f);

     // fill in the right face vertex data
     v[20] = Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
     v[21] = Vertex( 1.0f,  1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
     v[22] = Vertex( 1.0f,  1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
     v[23] = Vertex( 1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f);

     _vb->Unlock();// 索引缓存,索引都要记录每个三角形的顶点,6面体有12个三角形,36个索引顶点。
     _device->CreateIndexBuffer(
         36 * sizeof(WORD),
         D3DUSAGE_WRITEONLY,
         D3DFMT_INDEX16,
         D3DPOOL_MANAGED,
         &_ib,
         0);

     WORD* i = 0;
     _ib->Lock(0, 0, (void**)&i, 0);

     // fill in the front face index data
     i[0] = 0; i[1] = 1; i[2] = 2;
     i[3] = 0; i[4] = 2; i[5] = 3;

     // fill in the back face index data
     i[6] = 4; i[7]  = 5; i[8]  = 6;
     i[9] = 4; i[10] = 6; i[11] = 7;

     // fill in the top face index data
     i[12] = 8; i[13] =  9; i[14] = 10;
     i[15] = 8; i[16] = 10; i[17] = 11;

     // fill in the bottom face index data
     i[18] = 12; i[19] = 13; i[20] = 14;
     i[21] = 12; i[22] = 14; i[23] = 15;

     // fill in the left face index data
     i[24] = 16; i[25] = 17; i[26] = 18;
     i[27] = 16; i[28] = 18; i[29] = 19;

     // fill in the right face index data
     i[30] = 20; i[31] = 21; i[32] = 22;
     i[33] = 20; i[34] = 22; i[35] = 23;

     _ib->Unlock();
 }

 Cube::~Cube()
 {
     if(_vb){_vb->Release(); _vb = 0;}
     if(_ib){_ib->Release(); _ib = 0;}
 }

 bool Cube::draw(D3DXMATRIX* world, D3DMATERIAL9* mtrl, IDirect3DTexture9* tex)
 {
     if( world )
         _device->SetTransform(D3DTS_WORLD, world);
     if( mtrl )
         _device->SetMaterial(mtrl);
     if( tex )
         _device->SetTexture(0, tex);

     _device->SetStreamSource(0, _vb, 0, sizeof(Vertex));
     _device->SetIndices(_ib);
     _device->SetFVF(FVF_VERTEX);
     _device->DrawIndexedPrimitive(
         D3DPT_TRIANGLELIST, 
         0,                  
         0,                  
         24,
         0,
         12);  

     return true;
 }