整个graphics.cpp文件可以分成4个部分:内部接口;纹理相关;渲染对象相关;DX初始化等.
Texture & Target |
关于纹理的部分:
CTextureList struct CTextureList { HTEXTURE tex; int width; int height; CTextureList* next; }; |
Texture_Create(int width, int height) |
创建纹理
- D3DXCreateTexture创建一个纹理
HTEXTURE CALL HGE_Impl::Texture_Create(int width, int height) { LPDIRECT3DTEXTURE8 pTex; if( FAILED( D3DXCreateTexture( pD3DDevice, width, height, 1, // Mip levels 0, // Usage D3DFMT_A8R8G8B8, // Format D3DPOOL_MANAGED, // Memory pool &pTex ) ) ) { _PostError("Can't create texture"); return NULL; } return (HTEXTURE)pTex; }
Texture_Load(const char *filename, DWORD size, bool bMipmap) |
加载纹理 纹理和图片是不相同的!!!
- 先判断是否需要将文件从磁盘中读取到内存
- 然后在考虑文件的类型,并调用合适的参数:在这里有两个叠加的if语句,表示两种格式都测试,但是有一个格式为首先测试的!
- 最后是将纹理加载创建,并加入纹理列表:将原图的大小信息也加入纹理列表中
HTEXTURE CALL HGE_Impl::Texture_Load(const char *filename, DWORD size, bool bMipmap) { void *data; DWORD _size; D3DFORMAT fmt1, fmt2; LPDIRECT3DTEXTURE8 pTex; D3DXIMAGE_INFO info; CTextureList *texItem; if(size) { data=(void *)filename; _size=size; } else { data=pHGE->Resource_Load(filename, &_size); if(!data) return NULL; } if(*(DWORD*)data == 0x20534444) // Compressed DDS format magic number { fmt1=D3DFMT_UNKNOWN; fmt2=D3DFMT_A8R8G8B8; } else { fmt1=D3DFMT_A8R8G8B8; fmt2=D3DFMT_UNKNOWN; } // if( FAILED( D3DXCreateTextureFromFileInMemory( pD3DDevice, data, _size, &pTex ) ) ) pTex=NULL; if( FAILED( D3DXCreateTextureFromFileInMemoryEx( pD3DDevice, data, _size, D3DX_DEFAULT, D3DX_DEFAULT, bMipmap ? 0:1, // Mip levels 0, // Usage fmt1, // Format D3DPOOL_MANAGED, // Memory pool D3DX_FILTER_NONE, // Filter D3DX_DEFAULT, // Mip filter 0, // Color key &info, NULL, &pTex ) ) ) if( FAILED( D3DXCreateTextureFromFileInMemoryEx( pD3DDevice, data, _size, D3DX_DEFAULT, D3DX_DEFAULT, bMipmap ? 0:1, // Mip levels 0, // Usage fmt2, // Format D3DPOOL_MANAGED, // Memory pool D3DX_FILTER_NONE, // Filter D3DX_DEFAULT, // Mip filter 0, // Color key &info, NULL, &pTex ) ) ) { _PostError("Can't create texture"); if(!size) Resource_Free(data); return NULL; } if(!size) Resource_Free(data); texItem=new CTextureList; texItem->tex=(HTEXTURE)pTex; texItem->width=info.Width; texItem->height=info.Height; texItem->next=textures; textures=texItem; return (HTEXTURE)pTex; }
Texture_Free(HTEXTURE tex) |
释放纹理
- 在纹理列表中找到相应的纹理并释放
void CALL HGE_Impl::Texture_Free(HTEXTURE tex) { LPDIRECT3DTEXTURE8 pTex=(LPDIRECT3DTEXTURE8)tex; CTextureList *texItem=textures, *texPrev=0; while(texItem) { if(texItem->tex==tex) { if(texPrev) texPrev->next=texItem->next; else textures=texItem->next; delete texItem; break; } texPrev=texItem; texItem=texItem->next; } if(pTex != NULL) pTex->Release(); }
Texture_GetWidth(HTEXTURE tex, bool bOriginal) |
获得纹理的宽度
- 根据参数bOriginal来判断是获取纹理的宽度还是纹路中中加载的图片宽度
- 纹理的宽度可以通过GetLevelDesc来获取一个纹理表面的描述,再获得宽度
- 图片宽度可以通过纹理列表来获取
int CALL HGE_Impl::Texture_GetWidth(HTEXTURE tex, bool bOriginal) { D3DSURFACE_DESC TDesc; LPDIRECT3DTEXTURE8 pTex=(LPDIRECT3DTEXTURE8)tex; CTextureList *texItem=textures; if(bOriginal) { while(texItem) { if(texItem->tex==tex) return texItem->width; texItem=texItem->next; } return 0; } else { if(FAILED(pTex->GetLevelDesc(0, &TDesc))) return 0; else return TDesc.Width; } }
Texture_GetHeight(HTEXTURE tex, bool bOriginal) |
获得纹理的高度,类似宽度的操作
int CALL HGE_Impl::Texture_GetHeight(HTEXTURE tex, bool bOriginal) { D3DSURFACE_DESC TDesc; LPDIRECT3DTEXTURE8 pTex=(LPDIRECT3DTEXTURE8)tex; CTextureList *texItem=textures; if(bOriginal) { while(texItem) { if(texItem->tex==tex) return texItem->height; texItem=texItem->next; } return 0; } else { if(FAILED(pTex->GetLevelDesc(0, &TDesc))) return 0; else return TDesc.Height; } }
Texture_Lock(HTEXTURE tex, bool bReadOnly, int left, int top, int width, int height) |
锁定纹理区域
- GetLevelDesc获得纹理表面的信息
- 检测表面的模式是否允许
- 创建需要锁定的区域的矩阵
- LockRect锁定区域
- 返回锁定区域的字节
DWORD * CALL HGE_Impl::Texture_Lock(HTEXTURE tex, bool bReadOnly, int left, int top, int width, int height) { LPDIRECT3DTEXTURE8 pTex=(LPDIRECT3DTEXTURE8)tex; D3DSURFACE_DESC TDesc; D3DLOCKED_RECT TRect; RECT region, *prec; int flags; pTex->GetLevelDesc(0, &TDesc); if(TDesc.Format!=D3DFMT_A8R8G8B8 && TDesc.Format!=D3DFMT_X8R8G8B8) return 0; if(width && height) { region.left=left; region.top=top; region.right=left+width; region.bottom=top+height; prec=®ion; } else prec=0; if(bReadOnly) flags=D3DLOCK_READONLY; else flags=0; if(FAILED(pTex->LockRect(0, &TRect, prec, flags))) { _PostError("Can't lock texture"); return 0; } return (DWORD *)TRect.pBits; }
渲染目标部分:
CRenderTargetList struct CRenderTargetList { int width; int height; IDirect3DTexture8* pTex; IDirect3DSurface8* pDepth; CRenderTargetList* next; }; |
Target_Create(int width, int height, bool zbuffer) |
创建一个渲染对象
- 创建一个纹理D3DXCreateTexture
- 将纹理的长宽信息记录
- 根据zbuffer来调用CreateDepthStencilSurface
- 加入渲染目标的队列
HTARGET CALL HGE_Impl::Target_Create(int width, int height, bool zbuffer) { CRenderTargetList *pTarget; D3DSURFACE_DESC TDesc; pTarget = new CRenderTargetList; pTarget->pTex=0; pTarget->pDepth=0; if(FAILED(D3DXCreateTexture(pD3DDevice, width, height, 1, D3DUSAGE_RENDERTARGET, d3dpp->BackBufferFormat, D3DPOOL_DEFAULT, &pTarget->pTex))) { _PostError("Can't create render target texture"); delete pTarget; return 0; } pTarget->pTex->GetLevelDesc(0, &TDesc); pTarget->width=TDesc.Width; pTarget->height=TDesc.Height; if(zbuffer) { if(FAILED(pD3DDevice->CreateDepthStencilSurface(pTarget->width, pTarget->height, D3DFMT_D16, D3DMULTISAMPLE_NONE, &pTarget->pDepth))) { pTarget->pTex->Release(); _PostError("Can't create render target depth buffer"); delete pTarget; return 0; } } pTarget->next=pTargets; pTargets=pTarget; return (HTARGET)pTarget; }
Target_Free(HTARGET target) |
释放渲染对象
- 查找对象
- 释放纹理,释放表面
void CALL HGE_Impl::Target_Free(HTARGET target) { CRenderTargetList *pTarget=pTargets, *pPrevTarget=NULL; while(pTarget) { if((CRenderTargetList *)target == pTarget) { if(pPrevTarget) pPrevTarget->next = pTarget->next; else pTargets = pTarget->next; if(pTarget->pTex) pTarget->pTex->Release(); if(pTarget->pDepth) pTarget->pDepth->Release(); delete pTarget; return; } pPrevTarget = pTarget; pTarget = pTarget->next; } }
Target_GetTexture(HTARGET target) |
获得渲染对象的纹理
- 查找并获得渲染对象的纹理
HTEXTURE CALL HGE_Impl::Target_GetTexture(HTARGET target) { CRenderTargetList *targ=(CRenderTargetList *)target; if(target) return (HTEXTURE)targ->pTex; else return 0; }