粒子效果研究

粒子系統(tǒng)(Particle System)

粒子系統(tǒng)表示三維計算機圖形學(xué)中模擬一些特定的模糊現(xiàn)象的技術(shù),而這些現(xiàn)象用其它傳統(tǒng)的渲染技術(shù)難以實現(xiàn)的真實感的游戲圖形。經(jīng)常使用粒子系統(tǒng)模擬的現(xiàn)象,有火、爆炸、煙、水流、火花、落葉、云、霧、雪、塵、流星尾跡或者象發(fā)光軌跡這樣的抽象視覺效果等等。

粒子系統(tǒng)的特點

  1. 整個現(xiàn)象都是由很多個獨立的圖像效果組成,這些圖像效果都有自己的位置、移動軌跡等特點;
  2. 這些獨立的圖像效果組合或者疊加起來,就形成了要模擬的現(xiàn)象;
  3. 獨立的圖像效果經(jīng)過一段生命周期之后會從屏幕上消失,進而可以將其狀態(tài)重置并重新利用;

粒子系統(tǒng)的組成

  • 粒子類:每個單獨的粒子是整個粒子特效的一個基本組成部分,每個粒子都具有大量屬性,比如粒子圖片、生命時長、方向、速度、加速度等,這些屬性能夠決定粒子的外觀及行為表現(xiàn)。
  • 粒子發(fā)射器:實際上是所有粒子的管理者,是用來進行粒子生成、粒子控制、回收粒子的管理器類。

屬性設(shè)置

粒子系統(tǒng)中可以設(shè)置的屬性如下所示,不同平臺可能略有差異,但所遵守的標(biāo)準(zhǔn)相同,所以基本大同小異。

屬性設(shè)置.png

Cocos使用OpenGL混合原理對圖形進行渲染繪制?;旌暇褪侵赴褍煞N顏色混在一起,具體一點就是把某一像素位置原來的顏色和將要畫上去的顏色,通過某種方式混在一起,從而實現(xiàn)特殊的效果。它是一種常用的技巧,通常可以用來實現(xiàn)半透明,你也可以通過不同的設(shè)置得到不同的混合結(jié)果,產(chǎn)生一些有趣或者奇怪的圖象。具體可以參考:
https://www.andersriggelsen.dk/glblendfunc.php,下面是混合的集中模式,可以作用于src,

BlendFactor枚舉類型及其作用。

含義 作用
ONE 全部使用
ZERO 全部不用
SRC_ALPHA 使用源顏色的透明度
SRC_COLOR 使用源顏色
DST_ALPHA 使用目標(biāo)顏色的透明度
DST_COLOR 使用目標(biāo)顏色
ONE_MINUS_SRC_ALPHA 減去源顏色的透明度
ONE_MINUS_SRC_COLOR 減去源顏色
ONE_MINUS_DST_ALPHA 減去目標(biāo)顏色的透明度
ONE_MINUS_DST_COLOR 減去目標(biāo)顏色

關(guān)于粒子在cocos中的使用。

cocos create中提供了界面友好的工具供我們使用,粒子的簡單使用可以參考: https://docs.cocos.com/creator/manual/zh/asset-workflow/particle.html
我們可以在cocos中編輯這些粒子效果,在編輯的過程中可以預(yù)覽到粒子的實時效果,粒子相關(guān)的特性基本在plist中聲明即可。

粒子屬性.png

如果我們需要在cocos中通過代碼的形式控制到粒子動畫的播放和停止的話,可以resetSystem()來控制器展現(xiàn),利用stopSystem控制其隱藏。示例代碼如下:

//mA 表示要控制的粒子 ,即  mA: cc.ParticleSystem;
if(this.mA.active) {  
    this.mA.stopSystem();
} else {
    this.mA.resetSystem();
}

關(guān)于顏色計算

關(guān)于cocos源碼的實現(xiàn)

ParticleTest 測試類入口。
CCParticleExamples 測試主體類,主要在這里實現(xiàn)。

CCParticleSystem 是粒子系統(tǒng)的基類,提供對粒子的創(chuàng)建和更新管理。
ParticleSystemQuadCCParticleSystem 的子類,實現(xiàn)不需要批次結(jié)點時也能夠?qū)崿F(xiàn)粒子系統(tǒng)的OPENGL頂點和索引緩沖的創(chuàng)建和渲染.
CCParticleBatchNode 粒子系統(tǒng)的批次節(jié)點,用于將使用相同紋理的粒子系統(tǒng)進行同批次渲染優(yōu)化處理。

粒子系統(tǒng)實現(xiàn)類在CCParticleSystem中,其中包含了粒子系統(tǒng)的大部分實現(xiàn),下面是粒子系統(tǒng)中的幾個重要方法實現(xiàn)。

將粒子添加到粒子系統(tǒng)的實現(xiàn)(*)

這個是整個粒子系統(tǒng)運行的必要條件,想要粒子系統(tǒng)運行起來,必須得先將粒子加入到粒子系統(tǒng)中。相關(guān)代碼也比較復(fù)雜,比較多。
這里就不貼出具體的代碼,只給出關(guān)鍵的代碼:

void ParticleSystem::addParticles(int count)
{
    //life
    //position
    //color
    //size
    // rotation
    // position
    // Mode Gravity: 
    針對上面的屬性做賦值處理
}

粒子更新的實現(xiàn)

// ParticleSystem - MainLoop
void ParticleSystem::update(float dt)
{

    // 省略了一些屬性的設(shè)置調(diào)整。

    // 需要被重載的更新粒子的對應(yīng)矩形頂點緩沖信息塊的虛函數(shù),在這里進行界面更新
        updateParticleQuads();
        _transformSystemDirty = false;

    if (_visible && ! _batchNode)
    {
        postStep();
    }
}

粒子的屬性的動態(tài)設(shè)置都會在update中來完成,然后利用updateParticleQuads來更新指定粒子的頂點緩沖中的位置數(shù)據(jù),他的具體實現(xiàn)在CCParticleSystemQuad壘中,那么postStep做了什么呢,我們來看他的實現(xiàn),同樣,他的實現(xiàn)也在CCParticleSystemQuad中,

//針對不使用批次結(jié)點時的VBO頂點緩沖的更新。
void ParticleSystemQuad::postStep()
{
    //綁定頂點緩沖區(qū)對象。 
    glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
    
    //用_quads中數(shù)據(jù)更新綁定的緩沖區(qū)數(shù)據(jù)。
    // Option 1: Sub Data
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_quads[0])*_totalParticles, _quads);
    
    // Option 2: Data
    //  glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * particleCount, quads_, GL_DYNAMIC_DRAW);
    
    // Option 3: Orphaning + glMapBuffer
    // glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0])*_totalParticles, nullptr, GL_STREAM_DRAW);
    // void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
    // memcpy(buf, _quads, sizeof(_quads[0])*_totalParticles);
    // glUnmapBuffer(GL_ARRAY_BUFFER);
    
    //取消綁定緩沖區(qū)對象。
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    CHECK_GL_ERROR_DEBUG();
}

停止粒子系統(tǒng)的實現(xiàn)

這個實現(xiàn)就很簡單了,主要把_isActive設(shè)置為false即可。把開始到當(dāng)前的運行秒數(shù)_elapsed_duration賦值, 然后把每秒發(fā)射的粒子數(shù)_elapsed置為0,代碼如下:

void ParticleSystem::stopSystem()
{
    _isActive = false;
    _elapsed = _duration;
    _emitCounter = 0;
}

粒子重新啟動的實現(xiàn)

粒子系統(tǒng)重新啟動的實現(xiàn)也很簡單,主要是把所有的粒子的生命值置為0。

void ParticleSystem::resetSystem()
{
    _isActive = true;
    _elapsed = 0;
    for (int i = 0; i < _particleCount; ++i)
    {
        _particleData.timeToLive[i] = 0.0f;
    }
}

關(guān)于粒子系統(tǒng)屬性的設(shè)置

cocos 支持兩種方式的屬性設(shè)置,一種是通過字典,一種是通過plist文件。
通過字典的方式,就是手動去將元素的值賦值給字典,然后通過initWithDictionary方法來實現(xiàn)賦值,這種方式比較麻煩,而且也比較容易遺漏,所以我們一般采用第二種方式,即通過plist文件的形式來賦值。我們可以借助其他工具,生成plist文件,然后通過ParticleSystem::initWithFile來讀取這個文件,進行賦值。

術(shù)語

混合就是把兩種顏色混在一起。
具體一點,就是把某一像素位置原來的顏色和將要畫上去的顏色,通過某種方式混在一起,從而實現(xiàn)特殊的效果。

假設(shè)我們需要繪制這樣一個場景:透過紅色的玻璃去看綠色的物體,那么可以先繪制綠色的物體,再繪制紅色玻璃。在繪制紅色玻璃的時候,利用“混合”功能,把將要繪制上去的紅色和原來的綠色進行混合,于是得到一種新的顏色,看上去就好像玻璃是半透明的。

前面我們已經(jīng)提到,混合需要把原來的顏色和將要畫上去的顏色找出來,經(jīng)過某種方式處理后得到一種新的顏色。這里把將要畫上去的顏色稱為“源顏色”,如上例中的紅色;把原來的顏色稱為“目標(biāo)顏色”,如上例中的綠色。

目的顏色:先畫上的顏色(相當(dāng)于內(nèi)容)。
源顏色: 后畫上去的顏色(相當(dāng)于背景)。

VAO 用于存儲頂點數(shù)據(jù),包括頂點顏色、坐標(biāo)、法線,以及頂點的indices。
VBO 用于存儲圖形處理器將怎么使用VBO里面的數(shù)據(jù),及頂點數(shù)據(jù)中哪些是坐標(biāo)、哪些是顏色、哪些是法線等信息。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容