简易粒子系统
概念我不介绍了,其实实现起来也不是太难,大家可以去网上搜搜,我就不介绍了。
这个程序没有使用点精灵,而是使用了公告牌技术,而这个公告牌是基于视点的,计算方式我简要的说说。
设OXYZ坐标系中的一点P(x,y,z),我们要求对应于PUVN坐标系中位于同一坐标的点(x,y,z)在OXYZ坐标系中的位置,那么 这点在OXYZ中的位置为
x X U + y X V + z X N + P(视点位置)。(前面X是叉积)。那么我们设四点所在的平面在OXYZ坐标系中垂直于Z,那么转化到PUNV中也是同样垂直于Z的,因为他们在自己的坐标系中的坐标点相同,那么这就是公告牌了,U,V,N则分别根据你使用的基于视点还是基于视平面来计算,如果基于视点,则N = (Pos(公告牌位置) - Eye(观察点位置)) ,如果基于视平面的,那么U,V,N也就是视点坐标系的XYZ了。
D3DXVECTOR3 tmp = particlePos - eyePos;
float dis = D3DXVec3Length(&tmp);
D3DXVECTOR3 up(0,1,0);
D3DXVECTOR3 u, v;
D3DXVECTOR3 n = tmp;
D3DXVec3Cross(&u, &up, &n);
D3DXVec3Normalize(&u, &u); // get the x axis
D3DXVec3Cross(&v, &n, &u);
D3DXVec3Normalize(&v, &v); // get the y axis
D3DXVec3Normalize(&n, &n); // get the z axis
D3DXVECTOR3 Q1(-m_size, m_size, dis);
D3DXVECTOR3 Q2( m_size, m_size, dis);
D3DXVECTOR3 Q3( m_size,-m_size, dis);
D3DXVECTOR3 Q4(-m_size,-m_size, dis);
D3DXMATRIX mat(u.x, u.y, u.z, 0,
v.x, v.y, v.z ,0,
n.x, n.y, n.z ,0,
0, 0, 0, 1);
D3DXVec3TransformCoord(&Q1, &Q1, &mat);
D3DXVec3TransformCoord(&Q2, &Q2, &mat);
D3DXVec3TransformCoord(&Q3, &Q3, &mat);
D3DXVec3TransformCoord(&Q4, &Q4, &mat);
p[index].u = 0; p[index].v = 0; p[index++].pos = Q1 + eyePos;
p[index].u = 1; p[index].v = 0; p[index++].pos = Q2 + eyePos;
p[index].u = 1; p[index].v = 1; p[index++].pos = Q3 + eyePos;
p[index].u = 0; p[index].v = 1; p[index++].pos = Q4 + eyePos;
}
然后后面的就简单了。这里注意了如果使用DXUT 的CModelViewCamera会出现问题,我们只有使用CFirstPersonCamera.还有,如果不关闭深度测试,也会出现一些公告牌被遮挡的现象,我不明白为什么。所有图形是一次渲染,然后即使进行深度测试,但是我们的alpha混合也是打开的,也应该将后缓冲将被遮挡的点和现在的片源进行ALPHA混合,但是真实的情况却不是这样的。只能这样想了:一次DrawPrimitive绘制所有的图元,其中的ALPHA混合是将绘制图片之前的后备缓冲像素和当前的图元ALPHA混合,绘制完成后再更新一次,而不是每绘制一个图元变更新一次缓冲,这样效率太低了,所以我们关闭深度测试
应该加入脚本语言,方便编写粒子类型,但是我还不会,以后还会继续增加功能。
源代码下载地址: http://download.csdn.net/source/1797269