DirectX中利用COM的特性避免重复加载一个纹理

在DirectX的Mesh文件中,通常一个纹理可能作被几个材质共用。这是因为顶点是以属性分组的,只要材质和纹理不一样,就需要使用不同的属性。 而在一般的建模软件中,纹理常常被当成材质的一部分,导出时每个“材质”都有自己的纹理,这样做也是因为有时Mesh在不同的部分尽管使用相同的纹理,但是有不同的光照特性。DirectX的Mesh也是按照同样的方式组织材质,纹理和网格。
        DirectX提供的案例中,每个材质都分别加载一个纹理,可是,调试程序的时候,你会发现,有时只有几个纹理的物体,加载上来,有十几个材质,这样显然会有纹理被反复加载,那么我们可以使用COM的参照计数来避免这个问题。
        在加载一个材质对应纹理之前,先找一下前面的纹理有没有同名的,如果有,就把那个纹理的指针拷贝到这个材质对应的纹理指针,同时给这个被拷贝指针的纹理加上一个参考。那么以后释放它的时候就不用担心前面一个是否已经被释放了。
        COM是参照计数的,当增加一个参考时,计数器加1,释放一次时,计数器减1,如果计数器减到0,就把它从内存中释放掉。如果是使用了智能的指针,这个问题就更简单了,直接拷贝就可以了:

m_pMeshTextures[i]=m_pMeshTextures[j];

     
在DirectX的类型声明中可以看到,LPDIRECT3DTEXTURE9并不是一个智能指针:

typedef struct IDirect3DTexture9 *LPDIRECT3DTEXTURE9, *PDIRECT3DTEXTURE9;

所以在拷贝指针后要给这个COM对象的参考加1

m_pMeshTextures[j]->AddRef();


     

    m_pMeshMaterials = new D3DMATERIAL9[m_dwNumOfMaterials];            //材质指针数组
    m_pMeshTextures  = new LPDIRECT3DTEXTURE9[m_dwNumOfMaterials];        //纹理指针数组
    
    
for(DWORD i=0; i<m_dwNumOfMaterials; i++ )
    
{
        m_pMeshMaterials[i] 
= d3dxMaterials[i].MatD3D;                                //从缓冲区中拷贝材质
        m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;        //设置环境光属性
        m_pMeshTextures[i]  = NULL;                                                                  //初始成空
        
        
//根据材质中的纹理文件名加载纹理
        DWORD j=0;
        
while(j<i)
        
{    //避免重复加载纹理
            if(0==strcmp(d3dxMaterials[j].pTextureFilename, d3dxMaterials[i].pTextureFilename)) //找到同名纹理的序号
            
{
                m_pMeshTextures[i]
=m_pMeshTextures[j];  //直接拷贝指针而不是加载一次
                m_pMeshTextures[j]
->AddRef();                     //参考加1
                
break;    
            }
;
            j
++;
        }


        
if(! m_pMeshTextures[i])
        
{
            D3DXCreateTextureFromFile( m_pDevice, 
                d3dxMaterials[i].pTextureFilename, 
&m_pMeshTextures[i] );
        }


    }


在释放时,按照正常的方法释放就可以了

    for(DWORD i=0; i<m_dwNumOfMaterials; i++ )
    
{
        SAFE_RELEASE(m_pMeshTextures[i]);
    }

    SAFE_DELETE_ARRAY(m_pMeshTextures);
    SAFE_DELETE_ARRAY(m_pMeshMaterials);


posted @ 2005-09-27 21:58  JohnsonFeng  阅读(817)  评论(1编辑  收藏  举报