先看效果,按下空格键添加粒子特效:

一般而言粒子特效的实现都是比较复杂的,且不说实现粒子特效的编码和设计,光是编写一个粒子编辑器就不是简单的一件事,但是作者使用了很取巧的方式来完成,我们接下来深入代码看看作者是怎么处理的。

Particle

在我还没有看这本书的这章之前我认为一个Particle应该是一个单一的粒子(或许是一个面片或者是一个简单的模型),而最终的粒子效果则是有成千上万个Particle组成渲染得出的,所以应该存在一个JSON或XML描述文件来指定每个粒子的运动轨迹和生命周期,不过作者可不是这样想的。

作者的一个Particle类即表示一个在3D软件中渲染好的粒子群,如下图:

是的,一个粒子类其实就是加载了上面的模型,而所有的粒子其实都在模型中创建好了,按照作者的说法,这样可以实现批处理,即一次DrawCall可以绘制模型中的所有粒子(废话);

那么我们接着看,粒子类继承自Entity类,主要的改动是添加了Mesh2这个属性,表示该类可以解析两个模型,那么为啥要解析两个模型呢?

关键帧插值:

如果我们的粒子对象就是一个包含了多个粒子的Mesh模型,该如何控制具体的面片或小粒子进行缩放位移或旋转呢?答案就在关键帧插值这里,引入的Mesh2和Mesh的数据是一一对应的,但是具体的顶点数据的位置缩放或旋转不同(其实就是复制第一个模型文件在3DMax中微调以后输出的新文件);

如果存在Mesh2的数据我们会使用下面的这段顶点着色器代码:

 vertexShader.assemble
(
Context3DProgramType.VERTEX,
//换算起始坐标
"mul vt0, va0, vc4.xxxx\n" +
//换算终止坐标
"mul vt1, va2, vc4.yyyy\n" +
//在两个坐标里进行插值
"add vt2, vt0, vt1\n" +
//和 mvp 矩阵进行 4x4 运算
"m44 op, vt2, vc0\n" +
//将 uv 数据传递到片段着色器
"mov v1, va1"
);

我们把Mesh的顶点数据作为源xyz,Mesh2的顶点数据作为终点xyz,传递一个时间常量vc4进行插值计算,就可以得到平滑的关键帧过渡的效果了。

如果只有一个Mesh,则仅仅是输出原有坐标这么简单。

同时我们的片段着色器也进行了插值:

 fragmentShader.assemble
(
Context3DProgramType.FRAGMENT,
//对纹理进行取样
"tex ft0, v1, fs0 <2d,linear,repeat,miplinear>\n" +
//乘以淡入淡出矩阵
"mul ft0, ft0, fc0\n" +
//输出颜色
"mov oc, ft0\n"
);

我们传入的fc0的alpha会根据时间进行0到1到0的变化,来实现淡入淡出的效果;

不同角度观察的处理:

想要使一个粒子对象无论从任意的角度看都保持一致一般来说大部分的粒子都是使用Billboard系统,作者没有使用这个方法,而是将一个面片复制成三个,像xyz三个平面一样交叉起来,具体可以看上面的截图,这样无论从那个方向看都可以看见我们的粒子,但是效果没有Billboard的好。

渲染模式:

使用了ADD模式去掉纹理的黑边,同时去掉了深度检测,由于是最后才进行渲染所以特效会显示在所有3D内容的前方;

ParticleSystem

确切的说是一个粒子对象池,避免大量创建新的粒子对象,同时使用粒子对象的clone方法创建新的粒子来达到共用顶点数据和贴图的目的。

ParticleTest

添加了粒子特效的创建代码和更新代码,同时输出粒子特效的三角形数量,具体的大家可以看代码。

【Stage3D学习笔记续】真正的3D世界(五):粒子特效的更多相关文章

  1. 【Stage3D学习笔记续】山寨Starling(五):纹理计算和尺寸计算

    尺寸计算: Starling中的尺寸是以像素为单位的,这一切都得力于我们使用的正交矩阵,还记得我们顶点数据中的位置数据么,如果我们提交的矩形的四个顶点为(0, 0)(0, 100)(100, 0)(1 ...

  2. 【Stage3D学习笔记续】山寨Starling(八):核心优化(批处理)的实现

    批处理是使GPU进行高效绘制的一种技术手段,也是整个渲染流程中最核心的技术,到目前为止我们并没有使用到这种技术手段,下面我们看看我们现在的渲染机制. 先想一想我们最开始是怎么向GPU绘制一幅图像的,可 ...

  3. 【Stage3D学习笔记续】真正的3D世界(一):透视矩阵

    如果各位看官跟着我的学习笔记一路看过来的话,一定会吐槽我的,这都是什么3D啊?从头到尾整个都是在使用GPU绘制一堆2D图像而已,的确,之前我们一直使用正交矩阵利用GPU加速来实现2D世界的展示,算不上 ...

  4. 【Stage3D学习笔记续】真正的3D世界(六):空间大战

    这就是书上的最终效果了,一个完整的空间大战游戏: 点击查看源码 这里并没有太多的新知识,所涉及的东西更多的是游戏开发方面的优化和技巧,下面我们大家一起来看看: 飞船: 类似粒子效果中的粒子创建方法,我 ...

  5. 【Stage3D学习笔记续】真正的3D世界(二):显示模型

    虽然我们进入真3D世界了,但是上一章的Demo仍然是显示的一个平面,尽管我们的平面在3D空间中旋转可以看出一点3D透视的效果,但是既然是真3D,就要拿出点3D的样子来! 如果要显示3D模型,我们就要告 ...

  6. 【Stage3D学习笔记续】山寨Starling(二):VertexData探幽

    还记得之前的学习笔记中我们的顶点缓冲数组中的顶点数据么,我们使用一个一维数组来记录所有的顶点数据,这是由于顶点缓冲上传数据时是使用的一维数组. 如果对顶点数据进行一层代码的封装,就能更加的方便我们来操 ...

  7. 【Stage3D学习笔记续】真正的3D世界(四):空间大战雏形

    前面几个星期抽空用Starling做了一个打飞机的小游戏(所以没有接着看书了),准备面试时用的,结果面试还是没过%>_<%...这个游戏打算过几天全部开源了 那么接下来打算这周把<S ...

  8. 【Stage3D学习笔记续】真正的3D世界(三):纹理效果

    混合模式: 代码 示例是<Stage3D指南>中的直接弄出来的,可以通过点击键盘上的Q.W.E这3个按键,更换混合模式.模型和纹理,可以直观的查看不同混合模式的效果,住:下方的地形使用&q ...

  9. 【Stage3D学习笔记续】山寨Starling(十二):总结和一些没提到的东西

    我们的山寨Starling到这里就告一段落了,不得不说这是一个非常优秀的2D框架,他的设计和架构为后来的许多框架都提供了很好的参考,比如现在正在崛起的Egret,我们的一番解读也只是窥见了Starli ...

随机推荐

  1. Android:为控件绑定监听器

    为控件绑定监听器主要分为以下步骤: 1.获取代表控件的对象2.定义一个类,实现监听器接口3.生成监听器对象4.为控件绑定监听器对象 实例:Button按钮----监听器OnClickListener ...

  2. 我的JAVA基础学习史1

    又开始学习了..很是兴奋呢~~~~ 本来是想学安卓的,但是安卓的视频课程中,第一阶段是环境,第二阶段是JAVA基础(讲课的这个老师真是在念课本,但是实在没有办法,没找到更好.更完整的资料了). 虽然以 ...

  3. ADT中的代码补全设置

    设置自动补全代码 刚刚学Android,有很多变量和方法 都不熟悉.需要有提示,才更加方便. 快捷方式:Alt + /    可以出现代码提示. 默认的只有输入“ .” 以后才会有代码补全提示,可作如 ...

  4. poj2823

    这是一道题意简单,数据较大的题(喜闻乐见): 一开始可能会想到RMQ问题,ST,线段树都是O(nlogn),应该勉强能过(没试过): 由于这道题区间是滚动连续的,所以,可以使用单调队列! 以最小值为例 ...

  5. I.MX6 Linux 自动获取AR1020 event input节点

    /*********************************************************************** * I.MX6 Linux 自动获取AR1020 ev ...

  6. Apache配置虚拟目录和多主机头

    呃,相当古老的话题了,不过网上的资料实在是太坑爹,无奈只能自己动手做个备忘了...这里不提虚拟目录和主机头的区别了,不懂得童鞋去面壁思过吧 多个虚拟目录 首先把Apache安装到D:\Program ...

  7. xmlns 属性

    xmlns 属性 xmlns 属性可以在文档中定义一个或多个可供选择的命名空间.该属性可以放置在文档内任何元素的开始标签中.该属性的值类似于 URL,它定义了一个命名空间,浏览器会将此命名空间用于该属 ...

  8. NGINX(三)HASH表

    前言 nginx的hash表有几种不同的种类, 不过都是以ngx_hash_t为基础的, ngx_hash_t是最普通的hash表, 冲突采用的是链地址法, 不过这里冲突的元素不是一个链表, 而是一个 ...

  9. [selenium webdriver Java]使用自定义条件同步测试

    Selenium WebDriver可以结合ExpectedCondition类来定义自己期望的条件 创建一个新的ExpectedCondition接口,必须实现apply方法 等待元素出现 publ ...

  10. REST API TESTING

    在敏捷开发过程中 每隔两周就是一个sprint,,, 在上个sprint中,任务就是REST API TESTING 因为以前没做过API 测试,不懂,然后经过询问查找 终于知道,需要发送请求,然后获 ...