粒子效果研究

粒子系统(Particle System)

粒子系统表示三维计算机图形学中模拟一些特定的模糊现象的技术,而这些现象用其它传统的渲染技术难以实现的真实感的游戏图形。经常使用粒子系统模拟的现象,有火、爆炸、烟、水流、火花、落叶、云、雾、雪、尘、流星尾迹或者象发光轨迹这样的抽象视觉效果等等。

粒子系统的特点

  1. 整个现象都是由很多个独立的图像效果组成,这些图像效果都有自己的位置、移动轨迹等特点;
  2. 这些独立的图像效果组合或者叠加起来,就形成了要模拟的现象;
  3. 独立的图像效果经过一段生命周期之后会从屏幕上消失,进而可以将其状态重置并重新利用;

粒子系统的组成

  • 粒子类:每个单独的粒子是整个粒子特效的一个基本组成部分,每个粒子都具有大量属性,比如粒子图片、生命时长、方向、速度、加速度等,这些属性能够决定粒子的外观及行为表现。
  • 粒子发射器:实际上是所有粒子的管理者,是用来进行粒子生成、粒子控制、回收粒子的管理器类。

属性设置

粒子系统中可以设置的属性如下所示,不同平台可能略有差异,但所遵守的标准相同,所以基本大同小异。

属性设置.png

Cocos使用OpenGL混合原理对图形进行渲染绘制。混合就是指把两种颜色混在一起,具体一点就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。它是一种常用的技巧,通常可以用来实现半透明,你也可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象。具体可以参考:
https://www.andersriggelsen.dk/glblendfunc.php,下面是混合的集中模式,可以作用于src,

BlendFactor枚举类型及其作用。

含义 作用
ONE 全部使用
ZERO 全部不用
SRC_ALPHA 使用源颜色的透明度
SRC_COLOR 使用源颜色
DST_ALPHA 使用目标颜色的透明度
DST_COLOR 使用目标颜色
ONE_MINUS_SRC_ALPHA 减去源颜色的透明度
ONE_MINUS_SRC_COLOR 减去源颜色
ONE_MINUS_DST_ALPHA 减去目标颜色的透明度
ONE_MINUS_DST_COLOR 减去目标颜色

关于粒子在cocos中的使用。

cocos create中提供了界面友好的工具供我们使用,粒子的简单使用可以参考: https://docs.cocos.com/creator/manual/zh/asset-workflow/particle.html
我们可以在cocos中编辑这些粒子效果,在编辑的过程中可以预览到粒子的实时效果,粒子相关的特性基本在plist中声明即可。

粒子属性.png

如果我们需要在cocos中通过代码的形式控制到粒子动画的播放和停止的话,可以resetSystem()来控制器展现,利用stopSystem控制其隐藏。示例代码如下:

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

关于颜色计算

关于cocos源码的实现

ParticleTest 测试类入口。
CCParticleExamples 测试主体类,主要在这里实现。

CCParticleSystem 是粒子系统的基类,提供对粒子的创建和更新管理。
ParticleSystemQuadCCParticleSystem 的子类,实现不需要批次结点时也能够实现粒子系统的OPENGL顶点和索引缓冲的创建和渲染.
CCParticleBatchNode 粒子系统的批次节点,用于将使用相同纹理的粒子系统进行同批次渲染优化处理。

粒子系统实现类在CCParticleSystem中,其中包含了粒子系统的大部分实现,下面是粒子系统中的几个重要方法实现。

将粒子添加到粒子系统的实现(*)

这个是整个粒子系统运行的必要条件,想要粒子系统运行起来,必须得先将粒子加入到粒子系统中。相关代码也比较复杂,比较多。
这里就不贴出具体的代码,只给出关键的代码:

void ParticleSystem::addParticles(int count)
{
    //life
    //position
    //color
    //size
    // rotation
    // position
    // Mode Gravity: 
    针对上面的属性做赋值处理
}

粒子更新的实现

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

    // 省略了一些属性的设置调整。

    // 需要被重载的更新粒子的对应矩形顶点缓冲信息块的虚函数,在这里进行界面更新
        updateParticleQuads();
        _transformSystemDirty = false;

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

粒子的属性的动态设置都会在update中来完成,然后利用updateParticleQuads来更新指定粒子的顶点缓冲中的位置数据,他的具体实现在CCParticleSystemQuad垒中,那么postStep做了什么呢,我们来看他的实现,同样,他的实现也在CCParticleSystemQuad中,

//针对不使用批次结点时的VBO顶点缓冲的更新。
void ParticleSystemQuad::postStep()
{
    //绑定顶点缓冲区对象。 
    glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
    
    //用_quads中数据更新绑定的缓冲区数据。
    // 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);
    
    //取消绑定缓冲区对象。
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    CHECK_GL_ERROR_DEBUG();
}

停止粒子系统的实现

这个实现就很简单了,主要把_isActive设置为false即可。把开始到当前的运行秒数_elapsed_duration赋值, 然后把每秒发射的粒子数_elapsed置为0,代码如下:

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

粒子重新启动的实现

粒子系统重新启动的实现也很简单,主要是把所有的粒子的生命值置为0。

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

关于粒子系统属性的设置

cocos 支持两种方式的属性设置,一种是通过字典,一种是通过plist文件。
通过字典的方式,就是手动去将元素的值赋值给字典,然后通过initWithDictionary方法来实现赋值,这种方式比较麻烦,而且也比较容易遗漏,所以我们一般采用第二种方式,即通过plist文件的形式来赋值。我们可以借助其他工具,生成plist文件,然后通过ParticleSystem::initWithFile来读取这个文件,进行赋值。

术语

混合就是把两种颜色混在一起。
具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。

假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新的颜色,看上去就好像玻璃是半透明的。

前面我们已经提到,混合需要把原来的颜色和将要画上去的颜色找出来,经过某种方式处理后得到一种新的颜色。这里把将要画上去的颜色称为“源颜色”,如上例中的红色;把原来的颜色称为“目标颜色”,如上例中的绿色。

目的颜色:先画上的颜色(相当于内容)。
源颜色: 后画上去的颜色(相当于背景)。

VAO 用于存储顶点数据,包括顶点颜色、坐标、法线,以及顶点的indices。
VBO 用于存储图形处理器将怎么使用VBO里面的数据,及顶点数据中哪些是坐标、哪些是颜色、哪些是法线等信息。

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349