改進粒子系統-GPU實現

來源:互聯網
上載者:User

作者:fannyfish

Blog:http://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

 

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/fannyfish/archive/2006/06/14/797512.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.