用DirectX写的Skybox
实现原理:设置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; // 原始点
}
{
//
// 以下是基础数据
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;
}
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 ;
}
{
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;
}
{
m_vPos = vPos;
D3DXVECTOR3 v = m_vPos - m_vPosOrgin; // 计算出平移的向量
m_matWorld._41 = v.x;
m_matWorld._42 = v.y;
m_matWorld._43 = v.z;
}