目录

  1. 烟花爆竹场景和属性
  2. 实践以及遇到的问题
  3. 资料
  4. 收获

通过该篇的实践实现如下效果

一、烟花爆竹场景和属性

在上一篇 音视频开发之旅(15) OpenGL ES粒子系统 - 喷泉 的基础上 实现烟花爆炸效果。

在具体实践之前,先来想一想,烟花爆炸的场景和属性
场景:从中心点开始爆炸,然后烟花粒子向各个方向炸开,整体形状也各有不同,比如 北京奥运会的大脚印,但是大部分还是圆形(因为设计实现相对简单),今天我们也实现一个圆形的烟花爆炸效果。
属性:颜色、角度、运动矢量、形状。

实现流程和上一篇基本一致,不清晰整理的流程,建议先回看下

二、实践:烟花效果

在上篇的基础上通过修改Render的onDrawFrame中的粒子发射器来逐步实现烟花爆炸效果。

2.1 首先定义烟花爆炸对象
粒子的添加角度采用360度随机的方式添加

public class ParticleFireworksExplosion {private float[] mDirectionVector = {0f, 0f, 0.5f, 1f};private float[] mResultVector = new float[4];private final Random mRandom = new Random();private float[] mRotationMatrix = new float[16];public void addExplosion(ParticleSystem particleSystem, Geometry.Point position, int color, float curTime) {Matrix.setRotateEulerM(mRotationMatrix, 0, mRandom.nextFloat() * 360, mRandom.nextFloat() * 360, mRandom.nextFloat() * 360);Matrix.multiplyMV(mResultVector, 0, mRotationMatrix, 0, mDirectionVector, 0);particleSystem.addParticle(position,color,new Geometry.Vector(mResultVector[0],mResultVector[1],mResultVector[2]),curTime);}
}

2.2 然后在Render中使用ParticleFireworksExplosion作为粒子发射器

public class ParticlesRender implements GLSurfaceView.Renderer {...private ParticleFireworksExplosion particleFireworksExplosion;@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {...particleFireworksExplosion = new ParticleFireworksExplosion();}@Overridepublic void onDrawFrame(GL10 gl) {...//粒发射器添加粒子
//        mParticleShooter.addParticles(mParticleSystem,curTime,20);int color = Color.rgb(255, 50, 5);//烟花爆炸粒子发生器 添加粒子particleFireworksExplosion.addExplosion(mParticleSystem,new Geometry.Point(0,0f ,0),color,curTime);...}

效果如下:

问题1: 这明显不是烟花爆炸的效果

烟花爆炸是一个时间段只有一个爆炸,然后烟花颗粒向外圆形扩展开。而目前实现的效果是不断的发射新的粒子。

为此需要在onDrawFrame中间隔一段时间才发射粒子,这样让“烟花飞一会”从而形成烟花爆炸效果;同时,为了同一时间段粒子的数量保持一致,我们多同一个时间点我们同发射写粒子。具体实现如下:

public class ParticleFireworksExplosion {...private final int mPreAddParticleCount = 100;public void addExplosion(ParticleSystem particleSystem, Geometry.Point position, int color, float curTime) {//不是OnDrawFrame就添加烟花爆炸粒子,而是采用1/100的采样率 ,让粒子飞一会,从而产生烟花爆炸效果if (mRandom.nextFloat() < 1.0f / mPreAddParticleCount) {//同一时刻添加100个方向360随机的粒子for (int i = 0; i < mPreAddParticleCount; i++) {Matrix.setRotateEulerM(mRotationMatrix, 0, mRandom.nextFloat() * 360, mRandom.nextFloat() * 360, mRandom.nextFloat() * 360);Matrix.multiplyMV(mResultVector, 0, mRotationMatrix, 0, mDirectionVector, 0);particleSystem.addParticle(position,color,new Geometry.Vector(mResultVector[0],mResultVector[1],mResultVector[2]),curTime);}}}
}

效果如下:

问题2: 烟花扩散的效果不是圆形而是椭圆

这需要采用投影矩阵和视图矩阵变换 把椭圆形状投影到屏幕。

为此我们需要做如此处理

1.  顶点着色器中添加unifrom mat4,在gl_Position的赋值需要和改矩阵相乘。
2.  Program中解析该location以及进行数据的输入
3.  Render中进行透视矩阵和试图矩阵的定义和计算,生成matrix数据

具体实现如下:

1. 顶点着色器

uniform float u_Time;
uniform mat4 u_Matrix; //定义矩阵数据类型变量attribute vec3 a_Position;
attribute vec3 a_Color;
attribute vec3 a_Direction;
attribute float a_PatricleStartTime;varying vec3 v_Color;
varying float v_ElapsedTime;void main(){v_Color = a_Color;//粒子已经持续时间  当前时间-开始时间v_ElapsedTime = u_Time - a_PatricleStartTime;//重力或者阻力因子,随着时间的推移越来越大float gravityFactor = v_ElapsedTime * v_ElapsedTime / 9.8;//当前的运动到的位置 粒子起始位置+(运动矢量*持续时间)vec3 curPossition = a_Position + (a_Direction * v_ElapsedTime);//减去重力或阻力的影响curPossition.y -= gravityFactor;//把当前位置通过内置变量传给片元着色器。
//    gl_Position =  vec4(curPossition,1.0); //注释掉该实现,修改为下面的实现。//把当前位置和MVP矩阵相乘后,通过内置变量传给片元着色器gl_Position = u_Matrix * vec4(curPossition, 1.0);gl_PointSize = 25.0;
}

2. Program中解析和赋值matrix

public class ParticleShaderProgram {...private final String U_MATRIX = "u_Matrix";private final int uMatrixLocation;public ParticleShaderProgram(Context context) {...//获取uniform 和attribute的locationuMatrixLocation = glGetUniformLocation(program, U_MATRIX);...}/*** 设置Uniform变量* @param matrix* @param curTime*/public void setUniforms(float[] matrix, float curTime, int textureId){GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);...}
}

3. Render中进行透视矩阵和试图矩阵的定义和计算,生成matrix数据

public class ParticlesRender implements GLSurfaceView.Renderer {...private final float[] projectionMatrix = new float[16];private final float[] viewMatrix = new float[16];private final float[] viewProjectionMatrix = new float[16];@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {GLES20.glViewport(0,0,width,height);Matrix.perspectiveM(projectionMatrix, 0,45, (float) width/ (float) height, 1f, 10f);setIdentityM(viewMatrix, 0);translateM(viewMatrix, 0, 0f, -1.5f, -5f);multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0,viewMatrix, 0);}@Overridepublic void onDrawFrame(GL10 gl) {...//设置Uniform变量 mProgram.setUniforms(viewProjectionMatrix,curTime,mTextureId);}
}

效果如下:

问题3、目前的烟花都是红色的,如何实现多彩的烟花?

只需要修改粒子的颜色即可,我们通过hsv颜色空间,随机调节色调,然后转为rgb颜色空间的颜色值,赋值给粒子,具体实现如下

public class ParticleFireworksExplosion {private float[] mDirectionVector = {0f, 0f, 0.3f, 1f};private float[] mResultVector = new float[4];private final Random mRandom = new Random();private float[] mRotationMatrix = new float[16];private final int mPreAddParticleCount = 100;// 定义hsv色彩空间值,色调值默认为0(对应角度范围为0-360),饱和度和亮度默认为1(范围为0-2)private final float[] hsv = {0f, 1f, 1f};public void addExplosion(ParticleSystem particleSystem, Geometry.Point position, float curTime) {//不是OnDrawFrame就添加烟花爆炸粒子,而是采用1/100的采样率 ,让粒子飞一会,从而产生烟花爆炸效果if (mRandom.nextFloat() < 1.0f / mPreAddParticleCount) {//随机生成颜色的色调,hsv[0] = random.nextInt(360);//把hsv颜色空间转位rgb颜色空间值int color = Color.HSVToColor(hsv);//同一时刻添加100*3个方向360随机的粒子for (int i = 0; i < mPreAddParticleCount *3 ; i++) {Matrix.setRotateEulerM(mRotationMatrix, 0, mRandom.nextFloat() * 360, mRandom.nextFloat() * 360, mRandom.nextFloat() * 360);Matrix.multiplyMV(mResultVector, 0, mRotationMatrix, 0, mDirectionVector, 0);particleSystem.addParticle(position,color,new Geometry.Vector(mResultVector[0],mResultVector[1]+0.3f,//由于烟花弹向上的惯性,爆炸时添加向上的偏移,效果看起来更加逼真。mResultVector[2]),curTime);}}}
}

效果正如开篇展示

完整代码已上传至github

资料

《OpenGL ES 3.0 编程指南》
《OpenGL ES应用开发实践指南》

[粒子系统--烟花 [OpenGL-Transformfeedback]]
[Android制作粒子爆炸特效]
[Android超强大的粒子动画库,流星雨,爆炸,满屏飞花,等粒子特效快速实现]
[OpenGL进阶(六)-粒子系统]
[【OpenGL】Shader实例分析(七)- 雪花飘落效果]

收获

通过对OpenGL ES粒子系统的学习实践,发现通过粒子可以制作很多绚丽的效果。也在学习实践的过程中越来越发现路还很长,要不断持续学习实践才行。

具体到本篇收获
1. 分析烟花爆炸的场景与特性

2. 通过实践逐步实现多彩的烟花效果
3. 遇到的问题解决

感谢你的阅读

本来这个OpenGL ES系列计划还要写2-3篇,把天空盒、光照等也逐步学习实践,但是感觉到应用场景和整体方向目前来看关系性还不是很大。所以准备放大后续环节学习实践。下一篇我们开启JNI和NDK系列的学习实践。欢迎关注公众号“音视频开发之旅”,一起学习成长。

欢迎交流

音视频开发之旅(16) OpenGL ES粒子效果-烟花爆炸相关推荐

  1. 音视频开发系列(41)OpenGL ES粒子效果-烟花爆炸

    通过该篇的实践实现如下效果 一.烟花爆竹场景和属性 在上一篇OpenGL ES粒子系统 - 喷泉的基础上 实现烟花爆炸效果. 在具体实践之前,先来想一想,烟花爆炸的场景和属性 场景:从中心点开始爆炸, ...

  2. 音视频开发之旅(32)-音视频学习资料

    目录 为什么要学习音视频? 如何学习系统性音视频? 音视频相关的资料 学习实践的输出文章分类聚合 收获 最近有朋友问想学习音视频,应该怎么学,有什么资料吗? 这个问题也困扰我很久,几年前就想开始音视频 ...

  3. 音视频开发之旅(15) OpenGL ES粒子系统 - 喷泉

    目录 粒子和粒子系统 实践:喷泉效果 遇到的问题 资料 收获 通过该篇的实践实现如下效果 一.什么是粒子和粒子系统 如何定义粒子? 一个粒子有位置信息(x,y,z).运动方向.颜色.生命值(开始和结束 ...

  4. 安卓 camera 调用流程_音视频开发之旅(四)Camera视频采集

    目录 Camera基础知识 视频采集的流程 遇到的问题和常见的坑(重点) 收获 一. Camera基础知识 Camera 有几个重要的基础概念. facing相机的方向,一般后置摄像头和前置摄像头. ...

  5. 音视频开发之旅(36) -FFmpeg +OpenSL ES实现音频解码和播放

    目录 OpenSL ES基本介绍 OpenSL ES播放音频流程 代码实现 遇到的问题 资料 收获 上一篇我们通过AudioTrack实现了FFmpeg解码后的PCM音频数据的播放,在Android上 ...

  6. 音视频开发之旅(34) - 基于FFmpeg实现简单的视频解码器

    目录 FFmpeg解码过程流程图和关键的数据结构 mp4通过FFmpeg解码YUV裸视频数据 遇到的问题 资料 收获 一.FFmpeg解码过程流程图和关键的数据结构 FFmpeg解码涉及的知识点比较多 ...

  7. 音视频开发之旅(40)-贝塞尔曲线和曲面

    目录 贝塞尔曲线基本知识 画贝塞尔曲线 让曲线动起来 画贝塞尔曲面 资料 收获 本篇最终实现效果如下: 篇外说明:由于有必要学习使用下kotlin,后续的java层代码实现尽量采用kotlin 一.贝 ...

  8. 音视频开发之旅(二)AudioRecord录制PCM音频

    目录 音频采集API AudioRecord和MediaRecorder介绍 PCM的介绍 AudioRecord的使用(构造.开始录制.停止录制.其他细节点) ffplay播放pcm pcm转为wa ...

  9. 音视频开发之旅(38) -使用FBO实现渲染到纹理(Render to texture)

    目录 FBO基本知识 FBO实现渲染到纹理的流程 实践 遇到的问题 资料 收获 在之前的学习实践中我们把图片.视频.图形等渲染到屏幕时,采用的是直接屏幕上即默认的帧缓冲区,如果我们在渲染时不想直接渲染 ...

最新文章

  1. 虚幻4视频笔记002:精简StarterContent文件夹体积
  2. app h5 上传按钮多选_稿定小课堂之教你如何制作H5
  3. python中等于号可以用is代替_python中is与双等于号“==”的区别示例详解
  4. boost::mpi模块all_reduce() 集合的测试
  5. C++ DNN Opencv3.4 实现人脸计数和人脸检测
  6. 使用Java的BlockingQueue实现生产者-消费者
  7. C#基础精华05(正则表达式,)
  8. 详解VMware虚拟机中添加新硬盘并挂载的方法
  9. delphi计算机语言排名,2020年3月TIOBE编程语言排行榜 Java继续蝉联榜首
  10. 思维模型 SMART原则
  11. 怎样设置用键盘开机?
  12. 王者服务器维护5月1日,5月30日体验服停机更新公告
  13. 如何用 Ps 制作毛玻璃穿透效果?
  14. 解放生产力,VSCode使用小技巧
  15. 红帽linux7.2安装教程,RHEL 6.2安装(超级详细图解教程) | 系统运维
  16. 【Android】 Firebase登录、FCM、Google Play支付、adbrix、ONEStore、Galaxy Store、Google Install Referrer
  17. linux去除内容重复行,Linux删除文本中的重复行 - 米扑博客
  18. MKS电源维修RPG-50A射频电源维修OPTIMA RPG系列
  19. 在互联网上提问应该注意什么?
  20. 【05】概率图表示之马尔可夫随机场

热门文章

  1. 【熵与特征提取】从近似熵,到样本熵,到模糊熵,再到排列熵,究竟实现了什么?(第四篇)——“排列熵”及其MATLAB实现
  2. 时间序列分解论文STL: A Seasonal-Trend Decomposition Procedure Based on Loess
  3. 基于STM32+OneNet设计的物联网智慧路灯
  4. TokuDB和InnoDB的读写分析与比较
  5. shell脚本的$的含义
  6. 学c语言 pr用什么电脑配置,【答疑】学习python需要怎样的电脑配置? - 视频教程线上学...
  7. python画龙猫_龙猫Python简单学
  8. API接口开发其实特简单,Python FastApi Web 框架教程来了
  9. 现代软件企业竞争环境
  10. 中山纪念中学套题(1)