📄 game_skybox.cpp
字号:
#include "Game_User.h"
CSkyBox::CSkyBox(LPDIRECT3DDEVICE9 pDevice,float width,char *strTextureA6[])
{
m_pDevice=pDevice;
m_uSpeed=0.12f;
m_vSpeed=0.17f;
m_nSegment=16;
m_nSkyTile=15;
m_nAngle=D3DX_PI/4;
m_vPos.x=100;
m_vPos.y=100;
m_vPos.z=100;
m_fWidth=width;
if(strTextureA6)
{
for(int i=0;i<7;i++)
{
D3DXCreateTextureFromFile(m_pDevice, strTextureA6[i], &m_pTexture[i]);
}
}
else
{
for(int i=0;i<7;i++) m_pTexture[i]=NULL;
}
Initialize();
}
CSkyBox::~CSkyBox()
{
SAFE_RELEASE(m_pVBSky);
SAFE_RELEASE(m_pIBSky);
SAFE_RELEASE(m_pVB);
for(int i=0;i<7;i++)
{ if (m_pTexture[i])
{
/*delete m_pTexture[i];
m_pTexture[i]=NULL;*/
SAFE_RELEASE(m_pTexture[i]);
}
}
m_pDevice = NULL;
}
void CSkyBox::Render(float fFrameTime)
{
VERTEX_BOX *pV;
m_pVBSky->Lock(0,0,(void**)&pV,0);
//Refresh UV coordinate
if(pV[m_nSegment/2].tu<2.0f)
{
for(int i=0;i<(m_nSegment+1)*(m_nSegment+1) ;i++)
pV[i].tu+=m_uSpeed*fFrameTime;
}
else
{ float tu=pV[m_nSegment/2].tu;
for(int i=(m_nSegment+1)*(m_nSegment+1)-1;i>=0;i--)
pV[i].tu-=tu;
}
if(pV[m_nSegment/2].tv<2.0f)
{
for(int i=0;i<(m_nSegment+1)*(m_nSegment+1) ;i++)
pV[i].tv+=m_vSpeed*fFrameTime;
}
else
{ float tv=pV[m_nSegment/2].tv;
for(int i=(m_nSegment+1)*(m_nSegment+1)-1;i>=0;i--)
pV[i].tv-=tv;
}
m_pVBSky->Unlock();
//m_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_BLENDTEXTUREALPHA); //使用透明贴图
m_pDevice->SetRenderState( D3DRS_ZWRITEENABLE,FALSE); //关闭深度写入
m_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_BLENDTEXTUREALPHA);
m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
this->SetMatrix();
m_pDevice->SetFVF(D3DFVF_SKYBOX);
m_pDevice->SetStreamSource(0,m_pVB,0,sizeof(VERTEX_BOX));
m_pDevice->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_DISABLE);
for(int i=0;i<6;i++)
{
m_pDevice->SetTexture(0,m_pTexture[i]);
m_pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,i*4,2);
}
m_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_BLENDTEXTUREALPHA);
m_pDevice->SetTexture(0,m_pTexture[6]); //云的纹理
m_pDevice->SetStreamSource(0,m_pVBSky,0,sizeof(VERTEX_BOX));
m_pDevice->SetIndices(m_pIBSky);
m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,
(m_nSegment+1)*(m_nSegment+1),0,m_nSegment*m_nSegment*2);
m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
m_pDevice->SetRenderState( D3DRS_CLIPPLANEENABLE ,TRUE);
m_pDevice->SetRenderState( D3DRS_ZWRITEENABLE,TRUE);
}
// Function name : CSkyBox::Initialize
// Description :
// Return type : void
void CSkyBox::Initialize()
{
//天空盒
VERTEX_BOX VB[]=
{
{ 0.5f,-0.5f, 0.5f,-1.0f,0,0, 0.0f,1.0f,}, //East
{ 0.5f, 0.5f, 0.5f,-1.0f,0,0, 0.0f,0.0f,},
{ 0.5f,-0.5f, -0.5f,-1.0f,0,0, 1.0f,1.0f,},
{ 0.5f, 0.5f, -0.5f,-1.0f,0,0, 1.0f,0.0f,},
{ 0.5f,-0.5f, -0.5f,0,0,1.0f, 0.0f,1.0f,}, //North
{ 0.5f, 0.5f, -0.5f,0,0,1.0f, 0.0f,0.0f,},
{ -0.5f,-0.5f, -0.5f,0,0,1.0f, 1.0f,1.0f,},
{ -0.5f, 0.5f, -0.5f,0,0,1.0f, 1.0f,0.0f,},
{ -0.5f,-0.5f, -0.5f,1.0f,0,0, 0.0f,1.0f,}, //West
{ -0.5f, 0.5f, -0.5f,1.0f,0,0, 0.0f,0.0f,},
{ -0.5f,-0.5f, 0.5f,1.0f,0,0, 1.0f,1.0f,},
{ -0.5f, 0.5f, 0.5f,1.0f,0,0, 1.0f,0.0f,},
{-0.5f,-0.5f, 0.5f,0,0,-1.0f,0.0f,1.0f,}, //South
{-0.5f, 0.5f, 0.5f,0,0,-1.0f,0.0f,0.0f,},
{ 0.5f,-0.5f, 0.5f,0,0,-1.0f,1.0f,1.0f,},
{ 0.5f, 0.5f, 0.5f,0,0,-1.0f,1.0f,0.0f,},
{ -0.5f,-0.5f, 0.5f,0,1.0f,0, 0.0f,0.0f,}, //Earth
{ 0.5f,-0.5f, 0.5f,0,1.0f,0, 0.0f,1.0f,},
{ -0.5f,-0.5f, -0.5f,0,1.0f,0, 1.0f,0.0f,},
{ 0.5f,-0.5f, -0.5f,0,1.0f,0, 1.0f,1.0f,},
{ 0.5f, 0.5f, 0.5f,0,-1.0f,0, 0.0f,0.0f,}, //Sky
{-0.5f, 0.5f, 0.5f,0,-1.0f,0, 1.0f,0.0f,},
{ 0.5f, 0.5f, -0.5f,0,-1.0f,0, 0.0f,1.0f,},
{-0.5f, 0.5f, -0.5f,0,-1.0f,0, 1.0f,1.0f,},
};
//---------------------------------------------------------------------------------------------
//创建SkyDome,方形圆顶
//---------------------------------------------------------------------------------------------
int nVertex=(m_nSegment+1)*(m_nSegment+1); //289
int nIndex=m_nSegment*m_nSegment*6; //每个segment两个三角形,每个三角形3
//顶点,所以乘6
float R=0.5f/sinf(m_nAngle/2); //半径满足弧形宽度为1,和天空盒相等大小
//1.30656
VERTEX_BOX *VBSKY=new VERTEX_BOX[nVertex]; //顶点缓冲区
DWORD *IBSKY=new DWORD[nIndex]; //索引数据
float angleCol,angleRow;
float anglePerSeg=m_nAngle/m_nSegment; //0.049087
float angleStart=D3DX_PI/2-m_nAngle/2; //1.178097
float dYDown=R*sinf(angleStart); //云层向下的偏移量,边缘位于地平线上
//0.9238794
//1.207103
for (int i=0;i<nVertex;i++) //顶点数据
{
//---------------------------------------------------------------------------------------------
//等间角阵列
//---------------------------------------------------------------------------------------------
angleCol=angleStart+(i%(m_nSegment+1))*anglePerSeg;
angleRow=angleStart+(i/(m_nSegment+1))*anglePerSeg;
VBSKY[i].nx=-cosf(angleCol); //法线指向圆心
VBSKY[i].ny=-sinf(angleCol)*sinf(angleRow);
VBSKY[i].nz=-sinf(angleCol)*cosf(angleRow);
VBSKY[i].x=-R*VBSKY[i].nx;
VBSKY[i].y=-R*VBSKY[i].ny-dYDown; //偏移,边缘和地平线(y=0)平齐
VBSKY[i].z=-R*VBSKY[i].nz;
VBSKY[i].tu=m_nSkyTile*angleCol/m_nAngle;
VBSKY[i].tv=m_nSkyTile*angleRow/m_nAngle;
if(VBSKY[i].y<0.0f)
VBSKY[i].y=0.0f;
}
DWORD *lpIB=IBSKY; //索引数据
long iMax=(m_nSegment+1)*m_nSegment; //最后一个对应到矩形的左下角的顶点的索引号
for (int i=0;i<iMax;i++ )
{
if(i%(m_nSegment+1)!=m_nSegment) //每行的最后一个点不对应一个矩形
{
*(lpIB++)=i;
*(lpIB++)=i+m_nSegment+2; //每行顶点数量m_nSegment+1;
*(lpIB++)=i+m_nSegment+1;
/*
云的索引方式
0 3
_______
|\ |
| \ |
| \ |
2 |______\| 1
*/
*(lpIB++)=i;
*(lpIB++)=i+1;
*(lpIB++)=i+m_nSegment+2;
}
}
//天空盒
m_pDevice->CreateVertexBuffer(sizeof(VB),D3DUSAGE_WRITEONLY, D3DFVF_SKYBOX,
D3DPOOL_DEFAULT, &m_pVB,NULL);
void* pVertices;
m_pVB->Lock(0,0,&pVertices,0);
memcpy(pVertices,(void*)VB,sizeof(VB));
m_pVB->Unlock();
//云的顶点数据
m_pDevice->CreateVertexBuffer(sizeof(VERTEX_BOX)*nVertex, 0,
D3DFVF_SKYBOX, D3DPOOL_DEFAULT, &m_pVBSky,NULL);
m_pVBSky->Lock(0,0,&pVertices,0);
memcpy(pVertices,(void*)VBSKY,sizeof(VERTEX_BOX)*nVertex);
m_pVBSky->Unlock();
//天空的索引数据
m_pDevice->CreateIndexBuffer(sizeof(DWORD)*nIndex,0,D3DFMT_INDEX32,
D3DPOOL_DEFAULT, &m_pIBSky,NULL);
m_pIBSky->Lock(0,0,&pVertices,0);
memcpy(pVertices,(void*)IBSKY,sizeof(DWORD)*nIndex);
m_pIBSky->Unlock();
/*delete []IBSKY;
delete []VBSKY; */
SAFE_DELARRAY(IBSKY);
SAFE_DELARRAY(VBSKY);
}
// Function name : CSkyBox::LoadSkyBox
// Description :
// Return type : void
// Argument : char *strConfigFile
// Argument : char* strSkyName
void CSkyBox::LoadSkyBox(char *strConfigFile,char* strSkyName)
{
//当表达式为false时产生Debug信息(只对应Debug版本)
_ASSERT(!m_pTexture[0]);
char strFileName[256];
char *strKeyName[]=
{
"East",
"South",
"West",
"North",
"Earth",
"Sky",
"Cloud"
};
if(!m_pTexture[0])
{
for(int i=0;i<7;i++)
{
GetPrivateProfileString(strSkyName,strKeyName[i],"\0",strFileName,
sizeof(strFileName),strConfigFile);
/*LPCTSTR lpAppName ------- cfg文件中的一个字段名
LPCTSTR lpKeyName -------- lpAppName 下的一个键名,也就是里面具体的变量名
LPCTSTR lpDefaut ----------如果没有其前两个参数值,则将此值赋给变量
LPSTR lpReturnedString --------接收cfg文件中的值的CString对象,即接收缓冲区
DWORD nSize ------接收缓冲区的大小
LPCTSTR lpFileName --------完整的cfg文件路径名*/
_ASSERT(strFileName[0]);
D3DXCreateTextureFromFile(m_pDevice,strFileName, &m_pTexture[i]);
}
}
}
// Function name : CSkyBox::SetMatrix
// Description :
// Return type : void
void CSkyBox::SetMatrix()
{
//天空盒的位置总是随着摄像机在动
//天空盒在移动过程中会遮挡到地图,所以你看上去地形好像没了似的
//其实是地图某部分到了天空盒的外部
D3DXMATRIX matWorld;
matWorld._11=m_fWidth; matWorld._12=0; matWorld._13=0; matWorld._14=0;
matWorld._21=0; matWorld._22=m_fWidth; matWorld._23=0; matWorld._24=0;
matWorld._31=0; matWorld._32=0; matWorld._33=m_fWidth; matWorld._34=0;
matWorld._41=m_vPos.x; matWorld._42=m_vPos.y; matWorld._43=m_vPos.z; matWorld._44=1;
m_pDevice->SetTransform(D3DTS_WORLD,&matWorld);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -