改进粒子系统-GPU实现

原创 2006年06月14日 23:02:00

改进粒子系统-GPU实现

作者:fannyfish

Bloghttp://blog.csdn.net/fannyfish

amma@zsws.org

介绍

       即时粒子系统的性能主要受两个因素制约:填充率(fillrate)、CPU-GPU之间的数据传输。填充率即GPU每帧可以渲染的象素数,当粒子很大并且出现好多粒子重叠在一起的情况时会明显影响性能(比如用粒子模拟大面积水雾,烟尘)。通常的做法是先在CPU上进行粒子的物理运算,然后将运算结果传输给GPU渲染。当粒子数目巨大时(如100000个),运算时间和CPU-GPU的传输时间,对即时演算来说都难以接受(比如用粒子模拟大面积雨雪)。

       我做的项目中使用了大量粒子:场景特效、打击特效、甚至界面特效,无处不在。目前的粒子系统使用CPU进行物理运算。再加上物理引擎、骨骼融合、游戏逻辑,CPU成为了系统瓶颈,游戏中每帧GPU都要等待一短时间,显卡越好CPU越差越明显。如何将CPU的物理物理运算转移到GPU上,达到负载均衡是优化的关键。

设计

状态无关(Stateless vs 状态相关(State-preserving

       1,状态无关是指粒子的数据运算,都只根据初始的位置,速度等属性来计算。

       2,状态相关是指粒子的数据运算,可以根据上个状态的位置,速度等属性来计算。

       GPU上处理状态相关的粒子系统,需要多张纹理存储粒子状态,对显卡的要求很高。

相反,状态无关的粒子系统对显卡要求低,实现相对简单,所以首先考虑实现这种粒子系统。

与原有粒子系统的关系

       使用原有的粒子系统分为如下几个步骤:

1,  美术通过编辑器创建粒子

2,  在编辑器中指定粒子的渲染器,发射器,效果器。其中渲染器负责创建删除粒子对应的渲染数据(Billboard,模型),并维护渲染相关的状态。包括Billboard渲染器, 模型渲染器, Billboard拖尾渲染器, 模型拖尾渲染器。

3,  客户端使用,反馈给美术调整。

GPU上处理粒子系统,将使用不同的渲染数据和状态,因此派生一个新的渲染器:Shader渲染器。这样上面的步骤不会变化,美术只需要熟悉渲染器的新参数。

渲染数据和状态

       在没有使用到的纹理坐标和颜色VertexBuffer上存储顶点的初始属性。包括位置,颜色,在一个粒子quad上的位置(UpOffset, LeftOffset),速度,生存期。

       设置常量寄存器,包括world-view-proj矩阵,眼睛的Right向量Up向量(用来和UpOffset, LeftOffset计算不同的面向摄像机方式),时间,加速度,颜色变化量。

实现

引擎渲染代码段:

const static D3DVERTEXELEMENT9 g_VertexElements[] =

{

       { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_POSITION, 0},

       { 1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 0},

       { 2, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 1},

       { 3, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 2},     

       { 4, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 3},     

       { 5, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_COLOR,   0},

       D3DDECL_END()

};      

….

       m_pPositionVB = pDevice->CreateVertexBuffer( sizeof(v3dxVector3)*m_iVertexSize, m_pParent->m_dwVBUsage, m_pParent->m_Pool );

       m_pDiffuseVB = pDevice->CreateVertexBuffer( sizeof(DWORD)*m_iVertexSize, m_pParent->m_dwVBUsage, m_pParent->m_Pool );

       m_pTexCoordVB = pDevice->CreateVertexBuffer( sizeof(V3UV2)*m_iVertexSize, m_pParent->m_dwVBUsage, m_pParent->m_Pool );

       m_pTexCoordVB2 = pDevice->CreateVertexBuffer( sizeof(V3UV2)*m_iVertexSize, m_pParent->m_dwVBUsage, m_pParent->m_Pool );

       m_pTexCoordVB3 = pDevice->CreateVertexBuffer( sizeof(v3dxVector3)*m_iVertexSize, m_pParent->m_dwVBUsage, m_pParent->m_Pool );

       m_pIndexBuffer = pDevice->CreateIndexBuffer( sizeof(WORD)*m_iIndexSize, m_pParent->m_dwIBUsage, false, m_pParent->m_Pool );

填充粒子初始状态数据

 

       // 设置HLSL里的常量

       pEffect->SetMatrix("matWorldViewProj", (D3DXMATRIX *)&matTransformation);

       pEffect->SetVector("rightVector", &rightVector);

       pEffect->SetVector("upVector", &upVector);

       pEffect->SetVector("time_colour", &timeVec );

       pEffect->SetVector("acceleration", &acceleration );

       m_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST , 0, 0,pRenderer->m_iVertexSize, 0, pRenderer->m_iVertexSize/2 );

 

D3DFX代码:

struct VS_INPUT

{

    float3 Position                      : POSITION;   

    float2 Tex0                                 : TEXCOORD0;   

    float3 Tex1                                 : TEXCOORD1;    // UpOffset, LeftOffset, TotalTimeToLife

    float3 Tex2                                 : TEXCOORD2;    // Velocity

    float3 StartDiffuse                : COLOR0;           

};

 

struct VS_OUTPUT

{

    float4 Position                      : POSITION;

    float3 Diffuse                       : COLOR0;

    float2 Tex0                                 : TEXCOORD0;

};

 

matrix matWorldViewProj;                                               // world-view-proj matrix

float4 rightVector;                                                    // Right Vector

float4 upVector;                                                       // Up Vector

float4 time_colour;                                                  // Elasped Time, Delta Colour

float4 acceleration;       

 

VS_OUTPUT VS(const VS_INPUT Input)

{

    VS_OUTPUT    Out = (VS_OUTPUT) 0;

 

    // Position = right + up + pos;

    float4 right = rightVector * Input.Tex1.x;

    float4 up = upVector * Input.Tex1.y;

    float4 Pos = float4(Input.Position,0) + right + up;

 

    // Live Time = fmod( Elapsed Time, TotalTimeToLife )

    float fLiveTime = fmod(time_colour.x, Input.Tex1.z);

 

    // Position = Pos + vt + 1/2*v*t*t

    float4 deltaVel = mul( float4(Input.Tex2,0), fLiveTime);

    deltaVel = deltaVel + acceleration * fLiveTime * fLiveTime;

    //deltaVel.y = deltaVel.y + time_colour.z;

    Pos = Pos + deltaVel;

 

    Pos.w = 1.0;

    Out.Position = mul( Pos, matWorldViewProj );

 

    // color

       Out.Diffuse.x = Input.StartDiffuse.x + time_colour.y*fLiveTime;

    Out.Diffuse.y = Input.StartDiffuse.y + time_colour.z*fLiveTime;

    Out.Diffuse.z = Input.StartDiffuse.z + time_colour.w*fLiveTime;

 

    // texcoord

    Out.Tex0 = Input.Tex0;

 

    return Out;

}

 

technique tec0

{

    pass p0

    {

        VertexShader = compile vs_1_1 VS();

        PixelShader = NULL;

    }

}

编辑器中可调的属性

1, 默认高度

2, 默认宽度

3, 最大粒子数                    这里代表同时存在的粒子数

4, 粒子朝向

5, 面向摄像机的方式

6, 粒子UP向量          

7, 是否是2D粒子系统

发射器

8, 支持所有发射器和发射器特有属性(如圆环发射器的内环大小,外环大小)

9, 角度

10, 起始颜色

11, 结束颜色

12, 方向

13, 最小生存期

14, 最大生存期

15, 最小速度

16, 最大速度

17, 位置

效果器

18, 支持颜色衰减

19, 支持线性外力: "外力" 指加速度a, 满足公式s = vt + 1/2*a*t*t, 受力模式不起作用

截图

编辑器

1,point emitter, colour affector

2,box emitter, acceleration affector

其它

TODO

1,支持更多的Emitter, Affector. 根据粒子拥有的发射器,效果器类型动态编译不同的FX文件以减少运算量.(完成)

    http://blog.csdn.net/fannyfish/archive/2006/06/22/823032.aspx

 

2,支持State-Perspective粒子系统.(完成)

  http://blog.csdn.net/fannyfish/archive/2006/07/25/976753.aspx

3,排序,碰撞

4,支持设置粒子是相对世界坐标系还是本地坐标系

参考资料

1, [ShaderX3] Lutz Latta, Massively Parallel ParticleSystems on the GPU

2, [ShaderX2] O’dell Hicks, Screen-aligned Particles with Minimal VertexBuffer Locking

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

GPU上大规模粒子系统的Dx9实现细节总结

GPU上大规模粒子系统的Dx9实现细节总结 转自我们的博客http://www.xiaomingjia.com/?p=51 GPU上的粒子系统在DX10上的实现已经不是什么新鲜事了。考虑到公...
  • itlmy
  • itlmy
  • 2011-10-08 22:24
  • 564

Directx11基于GPU_GeometryShader的粒子系统

粒子系统作为在游戏中一个挺常见的技术,用在各种爆炸,下雨,火焰等特效中。我们利用GPU中的GeomtryShader来实现一个粒子系统。以下雨特效为例。     介绍粒子系统具体实现前先介绍下Geo...

Directx11基于GPU_GeometryShader的粒子系统

粒子系统作为在游戏中一个挺常见的技术,用在各种爆炸,下雨,火焰等特效中。我们利用GPU中的GeomtryShader来实现一个粒子系统。以下雨特效为例。     介绍粒子系统具体实现前先介绍下Geo...

粒子系统实现火焰效果

  • 2015-06-23 21:59
  • 620KB
  • 下载

【Visual C++】游戏开发五十 浅墨DirectX教程十八 雪花飞扬:实现唯美的粒子系统

本篇文章中,我们将一起探讨三维游戏中粒子系统的方方面面,首先对粒子系统的基本概念特性做一个全面的认知,然后我们依旧是把粒子系统封装在一个C++类中,模拟了三维游戏中唯美的雪花飞扬的景象,让我们之前的综...

粒子系统的实现

  • 2008-07-02 08:30
  • 49KB
  • 下载

【Cocos2d-x游戏引擎开发笔记(11)】粒子系统----实现下雪效果

原创文章,转载请注明出处:http://blog.csdn.net/zhy_cheng/article/details/8289683 太原市今天下雪了,8点出门,银装素裹,分外妖娆。今天就来主打下...

OpenGL实现的烟花粒子系统

OpenGL实现的烟花粒子效果,Win32和Android平台,非常漂亮。
  • ynnmnm
  • ynnmnm
  • 2011-10-27 14:48
  • 6021
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)