1. 基本原理
粒子系统由大量的粒子构成,每个粒子有大小,位置以及纹理,另外还有比如颜色,透明度,运动速度,加速度,自旋周期,生命周期等属性
粒子系统随时间不短变换,常经过下面几个变换
1)产生新的粒子
2)更新现有粒子属性
3)删除已经消亡的粒子
4)绘制出粒子
2. 粒子系统设计
1) 定义粒子数量,区域,宽度,高度
#define PARTICLE_NUMBER 10000
# define SNOW_SYSTEM_LENGTH_X 20000
#define SNOW_SYSTEM_WIDTH_Z 20000
#define SNOW_SYSTEM_HEIGHT_Y 20000
2)设置顶点结构和顶点格式,粒子系统类
struct POINTVERTEX{
float x,y,z;
float u,v;
};
#define D3DFVF_POINTVERTEX (DEDFVF_XYZ | D3DFVF_TEX1)
CParticleSystem::CParticleSystem()
{
m_NumParticles = 0;
m_pParticles = NULL;
m_fSpread = 0.0f;
m_fLifeSpan = 0.0f;
m_fStartSize = 0.0f;
m_fEndSize = 0.0f;
m_fSizeExponent = 0.0f;
m_fStartSpeed = 0.0f;
m_fEndSpeed = 0.0f;
m_fSpeedExponent = 0.0f;
m_fFadeExponent = 0.0f;
m_fRollAmount = 0.0f;
m_fWindFalloff = 0.0f;
m_vPosMul = D3DXVECTOR3( 0, 0, 0 );
m_vDirMul = D3DXVECTOR3( 0, 0, 0 );
m_fCurrentTime = 0.0f;
m_vCenter = D3DXVECTOR3( 0, 0, 0 );
m_fStartTime = 0.0f;
m_vFlashColor = D3DXVECTOR4( 0, 0, 0, 0 );
m_PST = PST_DEFAULT;
}
3. 初始化粒子数组
void CParticleSystem::Init()
{
for( UINT i = 0; i < m_NumParticles; i++ )
{
m_pParticles[i].vPos.x = RPercent() * m_fSpread;
m_pParticles[i].vPos.y = RPercent() * m_fSpread;
m_pParticles[i].vPos.z = RPercent() * m_fSpread;
m_pParticles[i].vPos.x *= m_vPosMul.x;
m_pParticles[i].vPos.y *= m_vPosMul.y;
m_pParticles[i].vPos.z *= m_vPosMul.z;
m_pParticles[i].vPos += m_vCenter;
m_pParticles[i].vDir.x = RPercent();
m_pParticles[i].vDir.y = fabs( RPercent() );
m_pParticles[i].vDir.z = RPercent();
m_pParticles[i].vDir.x *= m_vDirMul.x;
m_pParticles[i].vDir.y *= m_vDirMul.y;
m_pParticles[i].vDir.z *= m_vDirMul.z;
D3DXVec3Normalize( &m_pParticles[i].vDir, &m_pParticles[i].vDir );
m_pParticles[i].fRadius = m_fStartSize;
m_pParticles[i].fLife = m_fStartTime;
m_pParticles[i].fFade = 0.0f;
m_pParticles[i].fRot = RPercent() * 3.14159f * 2.0f;
float fLerp = RPercent();
D3DXVECTOR4 vColor = m_vColor0 * fLerp + m_vColor1 * ( 1.0f - fLerp );
m_pParticles[i].Color = ( DWORD )( vColor.w * 255.0f ) << 24;
m_pParticles[i].Color |= ( ( DWORD )( vColor.z * 255.0f ) & 255 ) << 16;
m_pParticles[i].Color |= ( ( DWORD )( vColor.y * 255.0f ) & 255 ) << 8;
m_pParticles[i].Color |= ( ( DWORD )( vColor.x * 255.0f ) & 255 );
}
m_bStarted = false;
m_fCurrentTime = m_fStartTime;
}
4.更新粒子系统
void CParticleSystem::AdvanceSystem( float fTime, float fElapsedTime, D3DXVECTOR3 vRight, D3DXVECTOR3 vUp,
D3DXVECTOR3 vWindVel, D3DXVECTOR3 vGravity )
{
if( m_fCurrentTime > 0 )
{
for( UINT i = 0; i < m_NumParticles; i++ )
{
float t = m_pParticles[i].fLife / m_fLifeSpan;
float tm1 = t - 1.0f;
float fSizeLerp = 1.0f - pow( tm1, m_fSizeExponent );
float fSpeedLerp = 1.0f - pow( tm1, m_fSpeedExponent );
float fFadeLerp = 1.0f - pow( tm1, m_fFadeExponent );
float fSize = fSizeLerp * m_fEndSize + ( 1.0f - fSizeLerp ) * m_fStartSize;
float fSpeed = fSpeedLerp * m_fEndSpeed + ( 1.0f - fSpeedLerp ) * m_fStartSpeed;
float fFade = fFadeLerp;
D3DXVECTOR3 vVel = m_pParticles[i].vDir * fSpeed;
float fRot = 0.0f;
float fWindAmt = 1.0f;
vVel += vWindVel * fWindAmt;
m_pParticles[i].vPos += fElapsedTime * vVel;
m_pParticles[i].fRadius = fSize;
m_pParticles[i].fLife += fElapsedTime;
m_pParticles[i].fFade = fFade;
m_pParticles[i].fRot += fRot;
m_pParticles[i].bVisible = true;
}
if( !m_bStarted )
{
m_bStarted = true;
}
}
else
{
for( UINT i = 0; i < m_NumParticles; i++ )
{
m_pParticles[i].bVisible = false;
m_pParticles[i].fLife += fElapsedTime;
}
}
m_fCurrentTime += fElapsedTime;
}
====================================================================================
介绍D3D sampler 中 deffer particle , 在射击类游戏中可以有非常绚丽效果,上图
其实呢,原理还是比较容易理解的
1. Alpha Blend
2.diffuse light