实现原理:设置5个面,即前、后、左、右、上5个,每个面4个顶点,共20个顶点,然后对每个面贴图,行走时,skybox与行走做相同的操作。下面一步步实现:
首先给出skybox的定义:
class CSkybox
{
//
//以下是基础数据
private:
D3DXMATRIXA16 m_matWorld; //世界矩阵
LPDIRECT3DTEXTURE9 m_pSideTexture[6]; //skybox的6个面的纹理
D3DXVECTOR3 m_vSize; // z, x, y分别为长,宽,高
D3DXVECTOR3 m_vPos; // skybox的中心点
D3DXVECTOR3 m_vPosOrgin; //原始点
}
1、设置skybox的大小和位置,即设置盒子的长宽高。
//设置位置
void SetBoxPos(const D3DXVECTOR3& vPos)
{
m_vPos = vPos; //当前点
m_vPosOrgin = m_vPos; //原始点
}
void SetBoxSize(const D3DXVECTOR3& vSize)
{
m_vSize = vSize;
}
2、创建顶点缓冲,顶点的位置要根据第一步的盒子大小创建。
实际上我只用了两张纹理,从CG模型网下载的古墓丽影的天空盒纹理,所以创建纹理坐标时是0.5。
BOOL CSkyBox::CreateVertexBuffer(LPDIRECT3DDEVICE9 p3DDevice9)
{
float fWidth = m_vSize.x;
float fLength = m_vSize.z;
float fHeight = m_vSize.y;
//确定8个点
//上面的左上角
D3DXVECTOR3 vTTopLeft(m_vPos.x - fWidth / 2, m_vPos.y + fHeight / 2, fLength / 2 - m_vPos.z);
D3DXVECTOR3 vTTopRight(fWidth / 2 - m_vPos.x, m_vPos.y + fHeight / 2, fLength / 2 - m_vPos.z);
D3DXVECTOR3 vTBottomLeft(m_vPos.x - fWidth / 2, m_vPos.y + fHeight / 2, m_vPos.z - fLength / 2);
D3DXVECTOR3 vTBottomRight(fWidth / 2 - m_vPos.x, m_vPos.y + fHeight / 2, m_vPos.z - fLength / 2);
//下面
D3DXVECTOR3 vBTopLeft(m_vPos.x - fWidth / 2, m_vPos.y - fHeight / 2, fLength / 2 - m_vPos.z);
D3DXVECTOR3 vBTopRight(fWidth / 2 - m_vPos.x, m_vPos.y - fHeight / 2, fLength / 2 - m_vPos.z);
D3DXVECTOR3 vBBottomLeft(m_vPos.x - fWidth / 2, m_vPos.y - fHeight / 2, m_vPos.z - fLength / 2);
D3DXVECTOR3 vBBottomRight(fWidth / 2 - m_vPos.x, m_vPos.y - fHeight / 2, m_vPos.z - fLength / 2);
CUSTOMVERTEX_TXT cvVertices[] =
{
//上面的点
{vTBottomLeft, D3DCOLOR_XRGB(255, 0, 0), 0.0f, 0.0f,}, //Vertex 2 - Red
{vTBottomRight, D3DCOLOR_XRGB(255, 255, 0), 1.0f, 0.0f,}, //Vertex 3 - Green
{vTTopLeft, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 1.0f,}, //Vertex 1 - Red
{vTTopRight, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 1.0f,}, //Vertex 0 - Blue
//前面
{vTTopLeft, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 0.0f,}, //Vertex 0 - Blue
{vTTopRight, D3DCOLOR_XRGB(255, 255, 255), 0.5f, 0.0f,}, //Vertex 1 - Red
{vBTopLeft, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 1.0f,}, //Vertex 2 - Red
{vBTopRight, D3DCOLOR_XRGB(255, 255, 255), 0.5f, 1.0f,}, //Vertex 3 - Green
//右面
{vTTopRight, D3DCOLOR_XRGB(255, 255, 255), 0.5f, 0.0f,}, //Vertex 0 - Blue
{vTBottomRight, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0.0f,}, //Vertex 3 - Green
{vBTopRight, D3DCOLOR_XRGB(255, 0, 0), 0.5f, 1.0f,}, //Vertex 2 - Red
{vBBottomRight, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 1.0f,}, //Vertex 1 - Red
//后面
{vTBottomRight, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 0.0f,}, //Vertex 0 - Blue
{vTBottomLeft, D3DCOLOR_XRGB(255, 255, 255), 0.5f, 0.0f,}, //Vertex 0 - Blue
{vBBottomRight, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 1.0f,}, //Vertex 1 - Red
{vBBottomLeft, D3DCOLOR_XRGB(255, 255, 255), 0.5f, 1.0f,}, //Vertex 1 - Red
//左面
{vTBottomLeft, D3DCOLOR_XRGB(255, 255, 255), 0.5f, 0.0f,}, //Vertex 0 - Blue
{vTTopLeft, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0.0f,}, //Vertex 0 - Blue
{vBBottomLeft, D3DCOLOR_XRGB(255, 255, 255), 0.5f, 1.0f,}, //Vertex 1 - Red
{vBTopLeft, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 1.0f,}, //Vertex 1 - Red
if(FAILED(p3DDevice9->CreateVertexBuffer(20 * sizeof(CUSTOMVERTEX_TXT),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &m_pVertexBuffer, NULL)))
{
return FALSE;
}
VOID* pVertices = NULL;
if(FAILED(m_pVertexBuffer->Lock(0, sizeof(cvVertices), (void**)&pVertices, 0)))
{
return FALSE;
}
//Copy our stored vertices values into the vertex buffer
memcpy(pVertices, cvVertices, sizeof(cvVertices));
//Unlock the vertex buffer
m_pVertexBuffer->Unlock();
return TRUE;
}
3、创建每个面的纹理。
4、更新世界矩阵。根据摄像头位置的改变,改变skybox的世界矩阵就行了。
void CSkyBox::UpdatePos(const D3DXVECTOR3& vPos)
{
m_vPos = vPos;
D3DXVECTOR3 v = m_vPos - m_vPosOrgin; //计算出平移的向量
m_matWorld._41 = v.x;
m_matWorld._42 = v.y;
m_matWorld._43 = v.z;
}