外部接口 |
这里的接口提供给用户进行固定的步骤:BeginScene;自己的渲染;EndScene。
接下来从教程2的渲染顺序来看函数
Gfx_BeginScene(HTARGET targ) |
在渲染前的准备工作
- TestCooperativeLevel 测试设备是否可用
- 如果在窗口模式下要检测BackBufferFormat,并更新BPP
- _GfxRestore 重设dx
- 检测顶点缓存:如果顶点缓存为不为0,则还未调用EndScene
- 在当前渲染对象并非参数中的渲染对象时:设置表面、渲染对象、设置渲染参数、设置投影矩阵、设置视图矩阵
- 设置为当前渲染对象
- IDirect3DDevice::BeginScene
- 锁定顶点缓存:等待顶点
bool CALL HGE_Impl::Gfx_BeginScene(HTARGET targ) { LPDIRECT3DSURFACE8 pSurf=0, pDepth=0; D3DDISPLAYMODE Mode; CRenderTargetList *target=(CRenderTargetList *)targ; HRESULT hr = pD3DDevice->TestCooperativeLevel(); if (hr == D3DERR_DEVICELOST) return false; else if (hr == D3DERR_DEVICENOTRESET) { if(bWindowed) { if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode)) || Mode.Format==D3DFMT_UNKNOWN) { _PostError("Can't determine desktop video mode"); return false; } d3dppW.BackBufferFormat = Mode.Format; if(_format_id(Mode.Format) < 4) nScreenBPP=16; else nScreenBPP=32; } if(!_GfxRestore()) return false; } if(VertArray) { _PostError("Gfx_BeginScene: Scene is already being rendered"); return false; } if(target != pCurTarget) { if(target) { target->pTex->GetSurfaceLevel(0, &pSurf); pDepth=target->pDepth; } else { pSurf=pScreenSurf; pDepth=pScreenDepth; } if(FAILED(pD3DDevice->SetRenderTarget(pSurf, pDepth))) { if(target) pSurf->Release(); _PostError("Gfx_BeginScene: Can't set render target"); return false; } if(target) { pSurf->Release(); if(target->pDepth) pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); else pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); _SetProjectionMatrix(target->width, target->height); } else { if(bZBuffer) pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); else pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); _SetProjectionMatrix(nScreenWidth, nScreenHeight); } pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj); D3DXMatrixIdentity(&matView); pD3DDevice->SetTransform(D3DTS_VIEW, &matView); pCurTarget=target; } pD3DDevice->BeginScene(); pVB->Lock( 0, 0, (BYTE**)&VertArray, 0 ); return true; }
Gfx_Clear(DWORD color) |
清理背景的工作
- 清理背景为指定的颜色
void CALL HGE_Impl::Gfx_Clear(DWORD color) { if(pCurTarget) { if(pCurTarget->pDepth) pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, color, 1.0f, 0 ); else pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, color, 1.0f, 0 ); } else { if(bZBuffer) pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, color, 1.0f, 0 ); else pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, color, 1.0f, 0 ); } }
Gfx_RenderQuad(const hgeQuad *quad) |
渲染矩形的准备工作
-
判断是否锁定顶点缓冲区
- 当前的渲染图元类型是否为矩阵 || 顶点是否超过 || 当前的纹理是否相同 || 渲染模式是否相同 : 只要一项不同,就先渲染当前的所有顶点,在渲染完后设置元数=0
-
将矩形的顶点导入顶点缓存
- 图元数增长
void CALL HGE_Impl::Gfx_RenderQuad(const hgeQuad *quad) { if(VertArray) { if(CurPrimType!=HGEPRIM_QUADS || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_QUADS || CurTexture!=quad->tex || CurBlendMode!=quad->blend) { _render_batch(); CurPrimType=HGEPRIM_QUADS; if(CurBlendMode != quad->blend) _SetBlendMode(quad->blend); if(quad->tex != CurTexture) { pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE8)quad->tex ); CurTexture = quad->tex; } } memcpy(&VertArray[nPrim*HGEPRIM_QUADS], quad->v, sizeof(hgeVertex)*HGEPRIM_QUADS); nPrim++; } }
Gfx_RenderTriple(const hgeTriple *triple) |
渲染三角形的准备工作
- 类似矩形
void CALL HGE_Impl::Gfx_RenderTriple(const hgeTriple *triple) { if(VertArray) { if(CurPrimType!=HGEPRIM_TRIPLES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_TRIPLES || CurTexture!=triple->tex || CurBlendMode!=triple->blend) { _render_batch(); CurPrimType=HGEPRIM_TRIPLES; if(CurBlendMode != triple->blend) _SetBlendMode(triple->blend); if(triple->tex != CurTexture) { pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE8)triple->tex ); CurTexture = triple->tex; } } memcpy(&VertArray[nPrim*HGEPRIM_TRIPLES], triple->v, sizeof(hgeVertex)*HGEPRIM_TRIPLES); nPrim++; } }
Gfx_RenderLine(float x1, float y1, float x2, float y2, DWORD color, float z) |
渲染直线的准备工作
- 判断是否锁定顶点缓冲区
- 当前的渲染图元类型是否为矩阵 || 顶点是否超过 || 当前的纹理是否相同 || 渲染模式是否相同 : 只要一项不同,就先渲染当前的所有顶点,在渲染完后设置元数=0
- 直线顶点导入顶点缓存
- 图元数增长
void CALL HGE_Impl::Gfx_RenderLine(float x1, float y1, float x2, float y2, DWORD color, float z) { if(VertArray) { if(CurPrimType!=HGEPRIM_LINES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_LINES || CurTexture || CurBlendMode!=BLEND_DEFAULT) { _render_batch(); CurPrimType=HGEPRIM_LINES; if(CurBlendMode != BLEND_DEFAULT) _SetBlendMode(BLEND_DEFAULT); if(CurTexture) { pD3DDevice->SetTexture(0, 0); CurTexture=0; } } int i=nPrim*HGEPRIM_LINES; VertArray[i].x = x1; VertArray[i+1].x = x2; VertArray[i].y = y1; VertArray[i+1].y = y2; VertArray[i].z = VertArray[i+1].z = z; VertArray[i].col = VertArray[i+1].col = color; VertArray[i].tx = VertArray[i+1].tx = VertArray[i].ty = VertArray[i+1].ty = 0.0f; nPrim++; } }
Gfx_EndScene() |
渲染工作结束
- 对顶点缓存中的所有顶点进行渲染;设置参数为true,在渲染结束之后顶点缓存vertarry=0
- IDirect3DDevice::EndScene
- IDirect3DDevice::Present 清理
void CALL HGE_Impl::Gfx_EndScene() { _render_batch(true); pD3DDevice->EndScene(); if(!pCurTarget) pD3DDevice->Present( NULL, NULL, NULL, NULL ); }
Gfx_StartBatch(int prim_type, HTEXTURE tex, int blend, int *max_prim) |
在批量渲染前的工作
- 获取顶点缓冲,并将原来的顶点渲染
- 设置当前的渲染图元、当前渲染混合模式、当前纹理
- 得到最大能渲染的个数
- 返回顶点缓存地址:准备载入顶点
hgeVertex* CALL HGE_Impl::Gfx_StartBatch(int prim_type, HTEXTURE tex, int blend, int *max_prim) { if(VertArray) { _render_batch(); CurPrimType=prim_type; if(CurBlendMode != blend) _SetBlendMode(blend); if(tex != CurTexture) { pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE8)tex ); CurTexture = tex; } *max_prim=VERTEX_BUFFER_SIZE / prim_type; return VertArray; } else return 0; }
Gfx_FinishBatch(int nprim) |
批量渲染前准备工作结束
- 设置需要渲染的图元的个数
void CALL HGE_Impl::Gfx_FinishBatch(int nprim) { nPrim=nprim; }
Gfx_SetClipping(int x, int y, int w, int h) |
设置裁剪
- 设置一个视口,并且设置视口的长、宽
- 然后将现有的顶点缓冲中的顶点渲染
- 设置视口
- 重新设置投影矩阵
void CALL HGE_Impl::Gfx_SetClipping(int x, int y, int w, int h) { D3DVIEWPORT8 vp; int scr_width, scr_height; if(!pCurTarget) { scr_width=pHGE->System_GetStateInt(HGE_SCREENWIDTH); scr_height=pHGE->System_GetStateInt(HGE_SCREENHEIGHT); } else { scr_width=Texture_GetWidth((HTEXTURE)pCurTarget->pTex); scr_height=Texture_GetHeight((HTEXTURE)pCurTarget->pTex); } if(!w) { vp.X=0; vp.Y=0; vp.Width=scr_width; vp.Height=scr_height; } else { if(x<0) { w+=x; x=0; } if(y<0) { h+=y; y=0; } if(x+w > scr_width) w=scr_width-x; if(y+h > scr_height) h=scr_height-y; vp.X=x; vp.Y=y; vp.Width=w; vp.Height=h; } vp.MinZ=0.0f; vp.MaxZ=1.0f; _render_batch(); pD3DDevice->SetViewport(&vp); D3DXMATRIX tmp; D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f); D3DXMatrixTranslation(&tmp, -0.5f, +0.5f, 0.0f); D3DXMatrixMultiply(&matProj, &matProj, &tmp); D3DXMatrixOrthoOffCenterLH(&tmp, (float)vp.X, (float)(vp.X+vp.Width), -((float)(vp.Y+vp.Height)), -((float)vp.Y), vp.MinZ, vp.MaxZ); D3DXMatrixMultiply(&matProj, &matProj, &tmp); pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj); }
Gfx_SetTransform(float x, float y, float dx, float dy, float rot, float hscale, float vscale) |
设置移动变换
- 通过参数对视图矩阵进行变换
- 渲染顶点缓冲中的所有顶点
- 重设投影矩阵
void CALL HGE_Impl::Gfx_SetTransform(float x, float y, float dx, float dy, float rot, float hscale, float vscale) { D3DXMATRIX tmp; if(vscale==0.0f) D3DXMatrixIdentity(&matView); else { D3DXMatrixTranslation(&matView, -x, -y, 0.0f); D3DXMatrixScaling(&tmp, hscale, vscale, 1.0f); D3DXMatrixMultiply(&matView, &matView, &tmp); D3DXMatrixRotationZ(&tmp, -rot); D3DXMatrixMultiply(&matView, &matView, &tmp); D3DXMatrixTranslation(&tmp, x+dx, y+dy, 0.0f); D3DXMatrixMultiply(&matView, &matView, &tmp); } _render_batch(); pD3DDevice->SetTransform(D3DTS_VIEW, &matView); }
图形模块 结束了!