3D游戏从入门到精通-12

时间:2022-05-25 19:58:21
 
1、             使用索引缓冲区
什么是索引缓冲区呢?其实索引缓冲区,就像指针一样的工具。顶点缓冲区里保存的是真实的顶点,而索引缓冲区只记录顶点缓冲区的顶点编号。比如顶点缓冲区里有4个顶点,而这4个顶点就可以构成两个三角形来显示。如果直接使用顶点缓冲区的话,就需要写6个顶点。这样就可以使用索引缓冲区,指明第一个三角形是由顶点编号1、2、3构成一个三角形,而第二个三角形就是1、3、4组成。
现在把上面的立方体改为使用索引缓冲区,先创建8个顶点,如下:
pVertices[0].vPosition = D3DXVECTOR3(    -1.0f, -1.0f, -1.0f ); 
pVertices[1].vPosition = D3DXVECTOR3(    -1.0f, 1.0f, -1.0f );   
pVertices[2].vPosition = D3DXVECTOR3(    1.0f, 1.0f, -1.0f );    
pVertices[3].vPosition = D3DXVECTOR3(    1.0f, -1.0f, -1.0f );   
 
pVertices[4].vPosition = D3DXVECTOR3(    -1.0f, 1.0f, 1.0f );    
pVertices[5].vPosition = D3DXVECTOR3(    1.0f, 1.0f, 1.0f );
pVertices[6].vPosition = D3DXVECTOR3(    1.0f, -1.0f, 1.0f );    
pVertices[7].vPosition = D3DXVECTOR3(    -1.0f, -1.0f, 1.0f );
这样,就可省下许多顶点占用的内存了,然后创建36个索引点的缓冲区,如下:
 
//创建索引缓冲区。
 hr = m_pd3dDevice->CreateIndexBuffer( 12*3 *sizeof(WORD),
       0, D3DFMT_INDEX16, D3DPOOL_DEFAULT,
       &m_pIB, NULL );
 
 if( FAILED( hr ) )
 {
       return E_FAIL;
 }   
 
上面创建了36个WORD大小的索引点,这样省了很多内存空间。由于顶点是由3个浮点数和其它值组成,肯定比两个字节索引值占用空间大。接着下来就是设置索引缓冲区,如下:
 
void* pIndices;
 
 if( FAILED( m_pIB->Lock( 0, sizeof(WORD)*12*3, &pIndices,0 ) ) )          
 {
       m_pIB->Release();
       m_pIB = NULL;
       return E_FAIL;
 }
 
 //
 WORD* pIndex = reinterpret_cast<WORD*>(pIndices);
 int nPos = 0;
 
 //1
 pIndex[nPos++] = 0;
 pIndex[nPos++] = 1;
 pIndex[nPos++] = 2;
 
 pIndex[nPos++] = 0;
 pIndex[nPos++] = 2;
 pIndex[nPos++] = 3;
 
 
 //2
 pIndex[nPos++] = 1;
 pIndex[nPos++] = 4;
 pIndex[nPos++] = 2;
 
 pIndex[nPos++] = 2;
 pIndex[nPos++] = 4;
 pIndex[nPos++] = 5;
 
 //3
 pIndex[nPos++] = 2;
 pIndex[nPos++] = 5;
 pIndex[nPos++] = 3;
 
 pIndex[nPos++] = 3;
 pIndex[nPos++] = 5;
 pIndex[nPos++] = 6;
 
 //4
 pIndex[nPos++] = 0;
 pIndex[nPos++] = 7;
 pIndex[nPos++] = 1;
 
 pIndex[nPos++] = 1;
 pIndex[nPos++] = 7;
 pIndex[nPos++] = 4;
 
 //5
 pIndex[nPos++] = 0;
 pIndex[nPos++] = 3;
 pIndex[nPos++] = 7;
 
 pIndex[nPos++] = 3;
 pIndex[nPos++] = 6;
 pIndex[nPos++] = 7;
 
 
 //6
 pIndex[nPos++] = 4;
 pIndex[nPos++] = 7;
 pIndex[nPos++] = 5;
 
 pIndex[nPos++] = 5;
 pIndex[nPos++] = 7;
 pIndex[nPos++] = 6;
 //
 m_pIB->Unlock();
 
上面这段代码,先Lock函数取得索引缓冲区地址,然后依次设置索引值,这里使用三角形列表,所以顶点顺序一样是按顺时针方向来设置的,也就是按左手坐标系来设置的。
接着下来,就需要渲染这个立方体了,如下:
m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(VT_CAICUBE) );
 m_pd3dDevice->SetFVF( VT_CAICUBE::dwFVF );
 
m_pd3dDevice->SetIndices(m_pIB);
m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,8,0,12);
上面代码先设置了8个顶点缓冲区到管道里,然后再调用SetIndices设置索引缓冲区,最后调用DrawIndexedPrimitive函数来显示所有三角形列表。DrawIndexedPrimitive函数的第一个参数是索引列表里的类型,第二个参数是索引缓冲区在顶点缓冲区里的起始位置,比如顶点缓区是0,1,3的,当设置这个值为50时,那么相当于访问了50,51,53的顶点值。第三个参数是最小索引值。第四个参数是有多少个顶点会使用。第五个参数是从那个索引值开始。第六个参数是基本图形个数。
 
通过这样学习,就学会使用了索引缓冲区,如果有很多顶点,有很多三角形,就需要使用优化的算法,以便有最少的顶点,使用最多的索引,这样有利于减少内存占用,提高带宽利用,提高显示卡显示更多图形,提高游戏的性能。
 
  
 
电子书 MM3D 引擎源程序 例子源程序 49 元一套
联系人:蔡军生  
联系方式:
QQ: 9073204
EMAIL: caimouse1976 at sina.com