现在的位置: 首页 > 综合 > 正文

Game Programming with DirectX — 11[粒子系统的实际应用]

2013年08月15日 ⁄ 综合 ⁄ 共 3439字 ⁄ 字号 评论关闭

 

Game Programming with DirectX -- 11[粒子系统的实际应用]

第十一集 粒子系统的实际应用

 

现实中的不规则物体要精确的模拟需要更多的粒子属性和更好的过程控制, 我们只是简单的模拟一些常见的物体.

 

以下粒子的参数初始化值和过程控制只是经验模型.

 

11.1 Snow

 

    创造虚拟的世界里的美丽"雪绒花".

 

11.1.1 参数初始化值

 

    雪花是从天空缓缓落下的, 随着风向飘散到大地....

(1). 初始位置Y值是一个比较大的正的数值, 表示从天空落下, XZ位置值可以是随机的正负值, 表示天空各个地方都会有雪花.

(2). 速度; 现实中有重力加速度的作用下落, 这里使用一简单的Y轴负值来模拟, XZ速度值随机的正负值, 模拟向各个方向飘散.

(3). 生命值; 由于雪花缓缓的飘落, 所以生命值适当的要长一点.

(4). 颜色; 雪花的纹理一般是白色的圆, 粒子颜色有无个人爱好决定.

m_vPos.x = randf(-16.0, 16.0); // X 初始值是 -16.0 16.0的随机值

m_vPos.y = 20.0;

m_vPos.z = randf(-16.0, 16.0);

m_vVel.x = randf(-0.1f, 0.1f);

m_vVel.y = randf(-0.2f, -0.1f);

m_vVel.z = randf(-0.1f, 0.1f);

m_fLife  = randf(16.0, 32.0);

 

11.1.2 过程控制

 

    雪花的过程控制是随机的减小生命值; 如果生命值大于零, 根据各个方向的速度更新位置; 如果生命值小于零, "删除"粒子 -- 实际是重新 初始化所有数值.

if (m_aP[i].m_fLife > 0.0)

{

   fRand = randf(0.0f, 0.2f);

   m_aP[i].m_fLife  -= fRand;

   m_aP[i].m_vPos.x += m_aP[i].m_vVel.x;

   m_aP[i].m_vPos.y += m_aP[i].m_vVel.y;

   m_aP[i].m_vPos.z += m_aP[i].m_vVel.z;

}

else

{

   m_aP[i].Init(g_nType);

}

11.1.3 绘制控制

 

    在上集的基础上, 在渲染粒子的时候关闭了Depth-Buffer的更新标志, 防止粒子因为离视点的远近关系, 远的粒子被近的粒子覆盖(会出现黑黑的正方形边框). 同样在渲染完毕后开启标志, 防止对后面的渲染有影响.

VOID CPSystem::EnterPSprite()

{

   FLOAT fSize = FLOAT(g_fSet * g_fSize);

   FLOAT fMin  = FLOAT(g_fMin * g_fSize);

   m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);

   m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

   m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

   m_pD3DDev->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);

   m_pD3DDev->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);

   m_pD3DDev->SetRenderState(D3DRS_POINTSIZE, FTOD(fSize));

   m_pD3DDev->SetRenderState(D3DRS_POINTSIZE_MIN, FTOD(fMin));

   m_pD3DDev->SetRenderState(D3DRS_POINTSCALE_A, FTOD(0.0f));

   m_pD3DDev->SetRenderState(D3DRS_POINTSCALE_B, FTOD(0.0f));

   m_pD3DDev->SetRenderState(D3DRS_POINTSCALE_C, FTOD(1.0f));

}

 

VOID CPSystem::ExitPSprite()

{

   m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

   m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

   m_pD3DDev->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);

   m_pD3DDev->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);

}

 

    如果整个渲染过程都不需要Depth-BufferZ-Buffer, 在创建IDirect3DDevice9时将创建的参数D3DPRESENT_PARAMETERSEnableAutoDepthStencil直接设为FALSE.这样就不必每次渲染粒子要开/D3DRS_ZWRITEENABLE标志.

D3DPRESENT_PARAMETERS d3dpm;

FillMemory(&d3dpm, sizeof(D3DPRESENT_PARAMETERS), 0);

//...

d3dpm.EnableAutoDepthStencil = FALSE;

//...

 

    下面的例子都需要开/D3DRS_ZWRITEENABLE标志

 

11.2 简单的喷泉

 

11.2.1 参数初始化值

 

(1). 初始位置一般是世界坐标原点.

(2). 速度; 首先有向上的Y轴速度, 然后在重力加速度的作用下Y轴速度变成负值, 也就是Y速度开始是正的, 随时间慢慢变小到负值. 例子中很偷懒, Y轴速度只是每帧减小一随机数值.

(3). 生命值; 个人爱好决定.

(4). 颜色; 个人爱好决定.

m_vPos.x = 0.0; // 初始位置是原点

m_vPos.y = 0.0;

m_vPos.z = 0.0;

m_vVel.x = randf(-0.02f, 0.02f);

m_vVel.y = randf(0.1f, 0.2f); // 初始Y值为正

m_vVel.z = randf(-0.02f, 0.02f);

m_fLife  = randf(8.0, 16.0);

 

11.2.2 过程控制

 

每一帧Y值减去一数值来模拟重力加速度的作用.

m_aP[i].m_fLife  -= fRand;

fRand = randf(-0.004f, 0.0f); // 减小的速度值随机生成

m_aP[i].m_vVel.y += fRand;

m_aP[i].m_vPos.x += m_aP[i].m_vVel.x;

m_aP[i].m_vPos.y += m_aP[i].m_vVel.y;

m_aP[i].m_vPos.z += m_aP[i].m_vVel.z;

 

 

11.3 简单的烟花

 

11.3.1 参数初始化值

 

烟花一般是五颜六色的, 沿一圆心球状向外扩散, 在重力加速度的作用下慢慢下降, 所以烟花的初始化数值比较特殊,

FLOAT fAlpha  = randf((-D3DX_PI / 2), (D3DX_PI / 2));

FLOAT fBeta   = randf(0.0, D3DX_PI * 2);

m_vPos.x = 0.0;

m_vPos.y = 10.0; // 初始位置(0, 10, 0)

m_vPos.z = 0.0;

m_vVel.x = cos(fAlpha) * sin(fBeta);

m_vVel.y = sin(fAlpha);

m_vVel.z = cos(fAlpha) * cos(fBeta);

m_fLife  = 8.0;

对于速度参数, 我们 初始化的数值是单位圆的经度和纬度, 烟花扩散的半径和生命值刚好相反.

 

 

11.3.2 过程控制

 

   每一帧粒子的位置是以初始位置为圆点, 生命值的相反数(这里是10.0 life), 同时Y轴还要减去模拟 重力加速度的作用, Y轴相应减去一数值

FLOAT fSize = 10.0f - m_aP[i].m_fLife;

m_aP[i].m_fLife -= 0.02f;

m_aP[i].m_vPos.x = fSize * m_aP[i].m_vVel.x;

m_aP[i].m_vPos.y = 10.0f + fSize * m_aP[i].m_vVel.y - fSize * 0.6f;

m_aP[i].m_vPos.z = fSize * m_aP[i].m_vVel.z;

 

 

11.4 简单的烟雾

 

<

抱歉!评论已关闭.