这里关于图形模块的内部接口部分
内部调用接口 |
内部接口主要完成:关于固定流水线的设置;dx的初始化;dx的结束
可以说内部接口已经完成了左右工作,只要进行组合调用即可
_GfxInit() |
DX的初始化函数
- Direct3DCreate8 创建接口
- GetAdapterIdentifier 获得设备信息,在这里可以查询设备能够做到什么
- PRESENT_PARAMETER 参数的填写
- CreateDevice 创建设备
- _AdjustWindow 这个函数原来在window模块里已经考虑过,在这里之所以调用是因为DX要和窗口之间关联,所以DX变化,窗口也随着调整
- _SetPorjectMatrix 设置投影矩阵
- D3DXMatirxIdentity 标准化视图矩阵
- _init_lost 在这个函数中完成顶点缓存、索引缓存、矩阵设置、渲染设置等
- Gfx_Clear 将窗口清理干净
bool HGE_Impl::_GfxInit() { static const char *szFormats[]={"UNKNOWN", "R5G6B5", "X1R5G5B5", "A1R5G5B5", "X8R8G8B8", "A8R8G8B8"}; D3DADAPTER_IDENTIFIER8 AdID; D3DDISPLAYMODE Mode; D3DFORMAT Format=D3DFMT_UNKNOWN; UINT nModes, i; // Init D3D pD3D=Direct3DCreate8(120); // D3D_SDK_VERSION if(pD3D==NULL) { _PostError("Can't create D3D interface"); return false; } // Get adapter info pD3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, D3DENUM_NO_WHQL_LEVEL, &AdID); System_Log("D3D Driver: %s",AdID.Driver); System_Log("Description: %s",AdID.Description); System_Log("Version: %d.%d.%d.%d", HIWORD(AdID.DriverVersion.HighPart), LOWORD(AdID.DriverVersion.HighPart), HIWORD(AdID.DriverVersion.LowPart), LOWORD(AdID.DriverVersion.LowPart)); // Set up Windowed presentation parameters if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode)) || Mode.Format==D3DFMT_UNKNOWN) { _PostError("Can't determine desktop video mode"); if(bWindowed) return false; } ZeroMemory(&d3dppW, sizeof(d3dppW)); d3dppW.BackBufferWidth = nScreenWidth; d3dppW.BackBufferHeight = nScreenHeight; d3dppW.BackBufferFormat = Mode.Format; d3dppW.BackBufferCount = 1; d3dppW.MultiSampleType = D3DMULTISAMPLE_NONE; d3dppW.hDeviceWindow = hwnd; d3dppW.Windowed = TRUE; if(nHGEFPS==HGEFPS_VSYNC) d3dppW.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC; else d3dppW.SwapEffect = D3DSWAPEFFECT_COPY; if(bZBuffer) { d3dppW.EnableAutoDepthStencil = TRUE; d3dppW.AutoDepthStencilFormat = D3DFMT_D16; } // Set up Full Screen presentation parameters nModes=pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT); for(i=0; i<nModes; i++) { pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT, i, &Mode); if(Mode.Width != (UINT)nScreenWidth || Mode.Height != (UINT)nScreenHeight) continue; if(nScreenBPP==16 && (_format_id(Mode.Format) > _format_id(D3DFMT_A1R5G5B5))) continue; if(_format_id(Mode.Format) > _format_id(Format)) Format=Mode.Format; } if(Format == D3DFMT_UNKNOWN) { _PostError("Can't find appropriate full screen video mode"); if(!bWindowed) return false; } ZeroMemory(&d3dppFS, sizeof(d3dppFS)); d3dppFS.BackBufferWidth = nScreenWidth; d3dppFS.BackBufferHeight = nScreenHeight; d3dppFS.BackBufferFormat = Format; d3dppFS.BackBufferCount = 1; d3dppFS.MultiSampleType = D3DMULTISAMPLE_NONE; d3dppFS.hDeviceWindow = hwnd; d3dppFS.Windowed = FALSE; d3dppFS.SwapEffect = D3DSWAPEFFECT_FLIP; d3dppFS.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; if(nHGEFPS==HGEFPS_VSYNC) d3dppFS.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; else d3dppFS.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if(bZBuffer) { d3dppFS.EnableAutoDepthStencil = TRUE; d3dppFS.AutoDepthStencilFormat = D3DFMT_D16; } d3dpp = bWindowed ? &d3dppW : &d3dppFS; if(_format_id(d3dpp->BackBufferFormat) < 4) nScreenBPP=16; else nScreenBPP=32; // Create D3D Device if( FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp, &pD3DDevice ) ) ) { _PostError("Can't create D3D device"); return false; } _AdjustWindow(); System_Log("Mode: %d x %d x %s ",nScreenWidth,nScreenHeight,szFormats[_format_id(Format)]); // Create vertex batch buffer VertArray=0; textures=0; // Init all stuff that can be lost _SetProjectionMatrix(nScreenWidth, nScreenHeight); D3DXMatrixIdentity(&matView); if(!_init_lost()) return false; Gfx_Clear(0); return true; }
_init_lost() 重要!重要!重要! |
在这个函数中实现:顶点缓存、索引缓存、矩阵设置、渲染设置
- GetRenderTarget & GetDepthStencilSurface
- 将渲染对象列表中的对象都导入:D3DXCreateTexture & CreateDepthStencilSurface
- CreateVertexBuffer 创建顶点缓存
- SetVertexShader 设置顶点格式
- SetStreamSource 设置顶点缓存
- CreateIndexBuffer 创建索引缓存
- IDirect3DIndexBuffer9::Lock 锁定索引缓冲区
- 初始化索引,这里设置为 {0,1,2 2,3,0}的方式两个两个三角形渲染
- IDirect3DIndexBuffer9::Unlock 解除索引缓冲区的锁定
- SetIndices 设定索引缓冲区
- 接下来设置渲染参数
- SetRenderState: D3DRS_CULLMODE,D3DRS_LIGHTING,D3DRS_ALPHABLENDENABLE,D3DRS_SRCBLEND,D3DRS_DESTBLEND,D3DRS_ALPHATESTENABLE,D3DRS_ALPHAREF,D3DRS_ALPHAFUNC
- SetTextureStageState: D3DTSS_COLOROP,D3DTSS_COLORARG1,D3DTSS_COLORARG1,D3DTSS_COLORARG2,D3DTSS_ALPHAOP,D3DTSS_ALPHAARG1,D3DTSS_ALPHAARG2,D3DTSS_MIPFILTER,D3DTSS_MAGFILTER,D3DTSS_MINFILTER
- 设置当前的需要渲染的图元个数
- 设置当前需要渲染的图元类型
- 设置当前BlendMode
- 设置当前的纹理
- SetTransform: D3DTS_VIEW,D3DTS_PROJECTION
bool HGE_Impl::_init_lost() { CRenderTargetList *target=pTargets; // Store render target pScreenSurf=0; pScreenDepth=0; pD3DDevice->GetRenderTarget(&pScreenSurf); pD3DDevice->GetDepthStencilSurface(&pScreenDepth); while(target) { if(target->pTex) D3DXCreateTexture(pD3DDevice, target->width, target->height, 1, D3DUSAGE_RENDERTARGET, d3dpp->BackBufferFormat, D3DPOOL_DEFAULT, &target->pTex); if(target->pDepth) pD3DDevice->CreateDepthStencilSurface(target->width, target->height, D3DFMT_D16, D3DMULTISAMPLE_NONE, &target->pDepth); target=target->next; } // Create Vertex buffer if( FAILED (pD3DDevice->CreateVertexBuffer(VERTEX_BUFFER_SIZE*sizeof(hgeVertex), D3DUSAGE_WRITEONLY, D3DFVF_HGEVERTEX, D3DPOOL_DEFAULT, &pVB ))) { _PostError("Can't create D3D vertex buffer"); return false; } pD3DDevice->SetVertexShader( D3DFVF_HGEVERTEX ); pD3DDevice->SetStreamSource( 0, pVB, sizeof(hgeVertex) ); // Create and setup Index buffer if( FAILED( pD3DDevice->CreateIndexBuffer(VERTEX_BUFFER_SIZE*6/4*sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &pIB ) ) ) { _PostError("Can't create D3D index buffer"); return false; } WORD *pIndices, n=0; if( FAILED( pIB->Lock( 0, 0, (BYTE**)&pIndices, 0 ) ) ) { _PostError("Can't lock D3D index buffer"); return false; } for(int i=0; i<VERTEX_BUFFER_SIZE/4; i++) { *pIndices++=n; *pIndices++=n+1; *pIndices++=n+2; *pIndices++=n+2; *pIndices++=n+3; *pIndices++=n; n+=4; } pIB->Unlock(); pD3DDevice->SetIndices(pIB,0); // Set common render states //pD3DDevice->SetRenderState( D3DRS_LASTPIXEL, FALSE ); pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); pD3DDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); pD3DDevice->SetRenderState( D3DRS_ALPHAREF, 0x01 ); pD3DDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ); pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT); if(bTextureFilter) { pD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_LINEAR); pD3DDevice->SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_LINEAR); } else { pD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_POINT); pD3DDevice->SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_POINT); } nPrim=0; CurPrimType=HGEPRIM_QUADS; CurBlendMode = BLEND_DEFAULT; CurTexture = NULL; pD3DDevice->SetTransform(D3DTS_VIEW, &matView); pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj); return true; }
_GfxDone() |
DX结束工作
- 删除所有的渲染对象:纹理、表面、本身
- 重新设置索引缓存,并释放现在的索引缓存
- 解除对顶点缓存的锁定并释放顶点缓存
- 释放D3D设备
- 释放D3D接口
void HGE_Impl::_GfxDone() { CRenderTargetList *target=pTargets, *next_target; while(textures) Texture_Free(textures->tex); if(pScreenSurf) { pScreenSurf->Release(); pScreenSurf=0; } if(pScreenDepth) { pScreenDepth->Release(); pScreenDepth=0; } while(target) { if(target->pTex) target->pTex->Release(); if(target->pDepth) target->pDepth->Release(); next_target=target->next; delete target; target=next_target; } pTargets=0; if(pIB) { pD3DDevice->SetIndices(NULL,0); pIB->Release(); pIB=0; } if(pVB) { if(VertArray) { pVB->Unlock(); VertArray=0; } pD3DDevice->SetStreamSource( 0, NULL, sizeof(hgeVertex) ); pVB->Release(); pVB=0; } if(pD3DDevice) { pD3DDevice->Release(); pD3DDevice=0; } if(pD3D) { pD3D->Release(); pD3D=0; } }
_GfxRestore() |
对于DX的复位操作 Reset
- 将当前的所有的渲染对象的纹理、表面释放
- 释放定点缓存和索引缓存
- IDirect3DDevice8::Reset
- _init_lost
bool HGE_Impl::_GfxRestore() { CRenderTargetList *target=pTargets; //if(!pD3DDevice) return false; //if(pD3DDevice->TestCooperativeLevel() == D3DERR_DEVICELOST) return; if(pScreenSurf) pScreenSurf->Release(); if(pScreenDepth) pScreenDepth->Release(); while(target) { if(target->pTex) target->pTex->Release(); if(target->pDepth) target->pDepth->Release(); target=target->next; } if(pIB) { pD3DDevice->SetIndices(NULL,0); pIB->Release(); } if(pVB) { pD3DDevice->SetStreamSource( 0, NULL, sizeof(hgeVertex) ); pVB->Release(); } pD3DDevice->Reset(d3dpp); if(!_init_lost()) return false; if(procGfxRestoreFunc) return procGfxRestoreFunc(); return true; }
_render_batch(bool bEndScene) |
批渲染,就是将在顶点缓存中的数据全部渲染
- 如果有顶点缓存的情况下才进行下面的步骤
- 对顶点缓存接触锁定
- 如果有图元要渲染,根据图元来分别渲染
- 渲染完图元之后通过参数判定是否要释放定点缓存
void HGE_Impl::_render_batch(bool bEndScene) { if(VertArray) { pVB->Unlock(); if(nPrim) { switch(CurPrimType) { case HGEPRIM_QUADS: pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, nPrim<<2, 0, nPrim<<1); break; case HGEPRIM_TRIPLES: pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, nPrim); break; case HGEPRIM_LINES: pD3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, nPrim); break; } nPrim=0; } if(bEndScene) VertArray = 0; else pVB->Lock( 0, 0, (BYTE**)&VertArray, 0 ); } }
_SetBlendMode(int blend) |
设置Blend Mode
- 如果需要的模式和当前的模式不同则设置为参数形式:
- BLEND_ALPHABLEND
- BLEND_ZWRITE
- BLEND_COLORADD
void HGE_Impl::_SetBlendMode(int blend) { if((blend & BLEND_ALPHABLEND) != (CurBlendMode & BLEND_ALPHABLEND)) { if(blend & BLEND_ALPHABLEND) pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); else pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); } if((blend & BLEND_ZWRITE) != (CurBlendMode & BLEND_ZWRITE)) { if(blend & BLEND_ZWRITE) pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); else pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); } if((blend & BLEND_COLORADD) != (CurBlendMode & BLEND_COLORADD)) { if(blend & BLEND_COLORADD) pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD); else pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); } CurBlendMode = blend; }
_SetProjectionMatrix(int width, int height) |
设置投影矩阵
- 通过矩阵操作设置投影矩阵
void HGE_Impl::_SetProjectionMatrix(int width, int height) { D3DXMATRIX tmp; D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f); D3DXMatrixTranslation(&tmp, -0.5f, height+0.5f, 0.0f); D3DXMatrixMultiply(&matProj, &matProj, &tmp); D3DXMatrixOrthoOffCenterLH(&tmp, 0, (float)width, 0, (float)height, 0.0f, 1.0f); D3DXMatrixMultiply(&matProj, &matProj, &tmp); }
_format_id(D3DFORMAT fmt) |
获得模式
- 预定了几个模式,判断给定的模式是否在其中并返回
int HGE_Impl::_format_id(D3DFORMAT fmt) { switch(fmt) { case D3DFMT_R5G6B5: return 1; case D3DFMT_X1R5G5B5: return 2; case D3DFMT_A1R5G5B5: return 3; case D3DFMT_X8R8G8B8: return 4; case D3DFMT_A8R8G8B8: return 5; default: return 0; } }