一. 公告板的應用:
公告板可被用於場景中對細節要求不高的樹木花草,也可用於玩家頭頂的某些特效表現等。其好處自然是高效簡潔。
二. 公告板基本原理:
公告板最基本的原理就是,繪製一個帶貼圖的矩形區域,由阿爾法混合使貼圖看起來更逼真,並且保證每幀矩形都是正對攝像機,從而在效果上表現出貼圖中的對象。 由於只繪製了一個矩形因此其繪製的性能很高。
三. 公告板實現方式及相關代碼:
由公告板的基本原理可以將其實現歸納爲以下步驟:
1. 初始化公告板矩形並將其放置到場景中
2. 每幀根據當前相機位置在XZ平面旋轉矩陣保證其正對攝像機(當相機可繞UP方向移動旋轉時會導致公告板穿幫,此時需要其他手段來解決。)
3. 繪製矩形並對其貼圖進行阿爾法混合。
具體相關代碼如下:
1. 初始化公告板矩形定點信息
a. 定義公告板定點信息
// 公告板定點信息
struct CUSTOMVERTEX
{
float x, y, z; //頂點位置
float u,v ; //頂點紋理座標
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)
b. 創建定點緩衝區
// 創建定點緩衝
pDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_MANAGED, &m_pVertexBuf, NULL );
// 初始化頂點數據 填充頂點緩衝區數據
CUSTOMVERTEX Vertices[] =
{
{ -m_fWidth / 2.0f, -m_fHeigh / 2.0f, 0.0f, 0.0f, 1.0f, },
{ -m_fWidth / 2.0f, m_fHeigh / 2.0f, 0.0f, 0.0f, 0.0f, },
{ m_fWidth / 2.0f, -m_fHeigh / 2.0f, 0.0f, 1.0f, 1.0f, },
{ m_fWidth / 2.0f, m_fHeigh / 2.0f, 0.0f, 1.0f, 0.0f, }
};
void* pVertices;
if( FAILED( m_pVertexBuf->Lock( 0, sizeof(Vertices), (void**)&pVertices,0 ) ) )
memcpy( pVertices, Vertices, sizeof(Vertices) );
m_pVertexBuf->Unlock();
c. 創建紋理貼圖
D3DXCreateTextureFromFileA( pDevice, pTexPath, &m_pTexture );
2. 每幀根據相機位置旋轉公告板
a. 計算相機朝向
VECTOR3 vPos;
pCamera->GetPostion( &vPos );
VECTOR3 vLookAt;
pCamera->GetLookAt( &vLookAt );
m_vCamera = vLookAt - vPos;
b. 更新公告板方向(只計算在XZ平面的方向爲了避免失真)
float fAngle = 0;
if( m_vCamera.x > 0.0f )
fAngle = -atanf(m_vCamera.z/m_vCamera.x)+D3DX_PI/2;
else
fAngle = -atanf(m_vCamera.z/m_vCamera.x)-D3DX_PI/2;
c. 設置旋轉矩陣
D3DXMatrixRotationY( &matRotation, fAngle + nIndex * m_nCount / D3DX_PI );
3. 設置紋理貼圖繪製公告板
a. 設置紋理阿爾法混合
pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
b. 繪製公告板
pDevice->SetTexture( 0, m_pTexture );
pDevice->SetStreamSource( 0, m_pVertexBuf, 0, sizeof(CUSTOMVERTEX) );
pDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
pDevice->SetTransform( D3DTS_WORLD, &matBillboard );
pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
四. 效果展示:
公告板 十字交叉公告板
五. 其他:
1. 關於十字交叉公告板:
所謂十字交叉公告板既是在公告板的基礎上再將矩形旋轉90度,使得兩個公告板交叉。十字交叉公告板比單純公告板表現效果更好。
2. 關於在UP方向旋轉相機導致公告板穿幫的問題可以採用在XZ平面增加一個頂部公告板的方式解決。