//=============================================================================
// Name: SnowParticleClass.h
// Des: 一个封装了雪花粒子系统系统的类的头文件
// 2013年 3月31日 Create by 浅墨
//=============================================================================
#pragma once
#include "D3DUtil.h"
#define PARTICLE_NUMBER 15000 //雪花粒子数量,显卡不好、运行起来卡的童鞋请取小一点。
#define SNOW_SYSTEM_LENGTH_X 20000 //雪花飞扬区域的长度
#define SNOW_SYSTEM_WIDTH_Z 20000 //雪花飞扬区域的宽度
#define SNOW_SYSTEM_HEIGHT_Y 20000 //雪花飞扬区域的高度
//-------------------------------------------------------------------------------------------------
//雪花粒子的FVF顶点结构和顶点格式
//-------------------------------------------------------------------------------------------------
struct POINTVERTEX
{
float x, y, z; //顶点位置
float u, v ; //顶点纹理坐标
};
#define D3DFVF_POINTVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)
//-------------------------------------------------------------------------------------------------
// Desc: 雪花粒子结构体的定义
//-------------------------------------------------------------------------------------------------
struct SNOWPARTICLE
{
float x, y, z; //坐标位置
float RotationY; //雪花绕自身Y轴旋转角度
float RotationX; //雪花绕自身X轴旋转角度
float FallSpeed; //雪花下降速度
float RotationSpeed; //雪花旋转速度
int TextureIndex; //纹理索引数
};
//-------------------------------------------------------------------------------------------------
// Desc: 粒子系统类的定义
//-------------------------------------------------------------------------------------------------
class SnowParticleClass
{
private:
LPDIRECT3DDEVICE9 m_pd3dDevice; //D3D设备对象
SNOWPARTICLE m_Snows[PARTICLE_NUMBER]; //雪花粒子数组
LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer; //粒子顶点缓存
LPDIRECT3DTEXTURE9 m_pTexture[6]; //雪花纹理数组
public:
SnowParticleClass(LPDIRECT3DDEVICE9 pd3dDevice); //构造函数
~SnowParticleClass(); //析构函数
HRESULT InitSnowParticle(); //粒子系统初始化函数
HRESULT UpdateSnowParticle( float fElapsedTime); //粒子系统更新函数
HRESULT RenderSnowParticle( ); //粒子系统渲染函数
};
//=============================================================================
// Name: SnowParticleClass.cpp
// Des: 一个封装了雪花粒子系统系统的类的源文件
// 2013年 3月31日 Create by 浅墨
//=============================================================================
#include "d3dx9.h"
#include "SnowParticleClass.h"
//-------------------------------------------------------------------------------------------------
// Desc: 构造函数
//-------------------------------------------------------------------------------------------------
SnowParticleClass::SnowParticleClass(LPDIRECT3DDEVICE9 pd3dDevice)
{
//给各个参数赋初值
m_pd3dDevice=pd3dDevice;
m_pVertexBuffer=NULL;
for(int i=0; i<5; i++)
m_pTexture[i] = NULL;
}
//-------------------------------------------------------------------------------------------------
// Name: SnowParticleClass::InitSnowParticle( )
// Desc: 粒子系统初始化函数
//-------------------------------------------------------------------------------------------------
HRESULT SnowParticleClass::InitSnowParticle( )
{
//初始化雪花粒子数组
srand(GetTickCount());
for(int i=0; i<PARTICLE_NUMBER; i++)
{
m_Snows[i].x = float(rand()%SNOW_SYSTEM_LENGTH_X-SNOW_SYSTEM_LENGTH_X/2);
m_Snows[i].z = float(rand()%SNOW_SYSTEM_WIDTH_Z-SNOW_SYSTEM_WIDTH_Z/2);
m_Snows[i].y = float (rand()%SNOW_SYSTEM_HEIGHT_Y);
m_Snows[i].RotationY = (rand()%100)/50.0f*D3DX_PI;
m_Snows[i].RotationX = (rand()%100)/50.0f*D3DX_PI;
m_Snows[i].FallSpeed = 300.0f + rand()%500;
m_Snows[i].RotationSpeed = 5.0f + rand()%10/10.0f;
m_Snows[i].TextureIndex = rand()%6;
}
//创建雪花粒子顶点缓存
m_pd3dDevice->CreateVertexBuffer( 4*sizeof(POINTVERTEX), 0,
D3DFVF_POINTVERTEX,D3DPOOL_MANAGED, &m_pVertexBuffer, NULL );
//填充雪花粒子顶点缓存
POINTVERTEX vertices[] =
{
{ -30.0f, 0.0f, 0.0f, 0.0f, 1.0f, },
{ -30.0f, 60.0f, 0.0f, 0.0f, 0.0f, },
{ 30.0f, 0.0f, 0.0f, 1.0f, 1.0f, },
{ 30.0f, 60.0f, 0.0f, 1.0f, 0.0f, }
};
//加锁
VOID* pVertices;
m_pVertexBuffer->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 );
//访问
memcpy( pVertices, vertices, sizeof(vertices) );
//解锁
m_pVertexBuffer->Unlock();
//创建6种雪花纹理
D3DXCreateTextureFromFile( m_pd3dDevice, L"GameMedia\\snow1.jpg", &m_pTexture[0] );
D3DXCreateTextureFromFile( m_pd3dDevice, L"GameMedia\\snow2.jpg", &m_pTexture[1] );
D3DXCreateTextureFromFile( m_pd3dDevice, L"GameMedia\\snow3.jpg", &m_pTexture[2] );
D3DXCreateTextureFromFile( m_pd3dDevice, L"GameMedia\\snow4.jpg", &m_pTexture[3] );
D3DXCreateTextureFromFile( m_pd3dDevice, L"GameMedia\\snow5.jpg", &m_pTexture[4] );
D3DXCreateTextureFromFile( m_pd3dDevice, L"GameMedia\\snow6.jpg", &m_pTexture[5] );
return S_OK;
}
//-------------------------------------------------------------------------------------------------
// Name: SnowParticleClass::UpdateSnowParticle( )
// Desc: 粒子系统更新函数
//-------------------------------------------------------------------------------------------------
HRESULT SnowParticleClass::UpdateSnowParticle( float fElapsedTime)
{
//一个for循环,更新每个雪花粒子的当前位置和角度
for(int i=0; i<PARTICLE_NUMBER; i++)
{
m_Snows[i].y -= m_Snows[i].FallSpeed*fElapsedTime;
//如果雪花粒子落到地面, 重新将其高度设置为最大
if(m_Snows[i].y<0)
m_Snows[i].y = SNOW_SYSTEM_WIDTH_Z;
//更改自旋角度
m_Snows[i].RotationY += m_Snows[i].RotationSpeed * fElapsedTime;
m_Snows[i].RotationX += m_Snows[i].RotationSpeed * fElapsedTime;
}
return S_OK;
}
//-------------------------------------------------------------------------------------------------
// Name: SnowParticleClass::RenderSnowParticle( )
// Desc: 粒子系统渲染函数
//-------------------------------------------------------------------------------------------------
HRESULT SnowParticleClass::RenderSnowParticle( )
{
//禁用照明效果
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false );
//设置纹理状态
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1) //将纹理颜色混合的第一个参数的颜色值用于输出
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //纹理颜色混合的第一个参数的值就取纹理颜色值
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); //缩小过滤状态采用线性纹理过滤
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); //放大过滤状态采用线性纹理过滤
//设置Alpha混合系数,透明贴图,将图片背景黑色去掉
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); //打开Alpha混合
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); //源混合系数设为1
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); //目标混合系数设为1
//设置背面消隐剔除模式为不剔除任何面
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
//渲染雪花
for(int i=0; i<PARTICLE_NUMBER; i++)
{
//构造并设置当前雪花粒子的世界矩阵
static D3DXMATRIX matYaw, matPitch, matTrans, matWorld;
D3DXMatrixRotationY(&matYaw, m_Snows[i].RotationY);
D3DXMatrixRotationX(&matPitch, m_Snows[i].RotationX);
D3DXMatrixTranslation(&matTrans, m_Snows[i].x, m_Snows[i].y, m_Snows[i].z);
matWorld = matYaw * matPitch * matTrans;
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld);
//渲染当前雪花粒子
m_pd3dDevice->SetTexture( 0, m_pTexture[m_Snows[i].TextureIndex] ); //设置纹理
m_pd3dDevice->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(POINTVERTEX)); //把包含的几何体信息的顶点缓存和渲染流水线相关联
m_pd3dDevice->SetFVF(D3DFVF_POINTVERTEX); //设置FVF灵活顶点格式
//从第0个点开始用D3DPT_TRIANGLELIST 模式渲染2个三角形
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); //绘制
}
//恢复相关渲染状态:Alpha混合 、剔除状态、光照
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, true );
return S_OK;
}
//-------------------------------------------------------------------------------------------------
// Desc: 析构函数
//-------------------------------------------------------------------------------------------------
SnowParticleClass::~SnowParticleClass()
{
SAFE_RELEASE(m_pVertexBuffer);
for(int i=0;i<3; i++)
{
SAFE_RELEASE(m_pTexture[i]);
}
}
调用:
描述:全局变量的声明
SnowParticleClass* g_pSnowParticles = NULL; //雪花粒子系统的指针实例
Objects_Init()
描述:渲染资源初始化函数,在此函数中进行要被渲染的物体的资源的初始化
//创建并初始化雪花粒子系统
g_pSnowParticles = new SnowParticleClass(g_pd3dDevice);
g_pSnowParticles->InitSnowParticle();
Direct3D_Render()
描述:使用Direct3D进行渲染
//绘制雪花粒子系统
g_pSnowParticles->UpdateSnowParticle(fTimeDelta);
g_pSnowParticles->RenderSnowParticle();
WinMain()
//消息循环过程
MSG msg = { 0 }; //初始化msg
while( msg.message != WM_QUIT ) //使用while循环
{
static FLOAT fLastTime = (float)::timeGetTime();
static FLOAT fCurrTime = (float)::timeGetTime();
static FLOAT fTimeDelta = 0.0f;
fCurrTime = (float)::timeGetTime();
fTimeDelta = (fCurrTime - fLastTime) / 1000.0f;
fLastTime = fCurrTime;
if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) //查看应用程序消息队列,有消息时将队列中的消息派发出去。
{
TranslateMessage( &msg ); //将虚拟键消息转换为字符消息
DispatchMessage( &msg ); //该函数分发一个消息给窗口程序。
}
else
{
Direct3D_Update(hwnd,fTimeDelta); //调用更新函数,进行画面的更新
Direct3D_Render(hwnd,fTimeDelta); //调用渲染函数,进行画面的渲染
}
}