directory

  1. Fireworks scenes and attributes
  2. Practice and problems encountered
  3. data
  4. harvest

Through the practice of this article to achieve the following results

First, fireworks scenes and attributes

In the last audio and video development journey (15) OpenGL ES particle system – fountain based on the implementation of fireworks explosion effect.

Before the concrete practice, first to think of it, a blast scenarios and attribute of the scene: starting from the center of explosion, then the fireworks particles in all directions, the overall shape is different also, the big footprints of Beijing Olympic Games, for example, but mostly circular (because design to achieve relatively simple), today we also implement a circular blast effect. Properties: color, Angle, motion vector, shape.

The implementation process is basically the same as the previous one. If the process is not clear, it is recommended to review it first

Two, practice: fireworks effect

On the basis of the previous chapter by modifying the Render onDrawFrame particle emitter to gradually achieve the effect of fireworks explosion.

2.1 Firstly define the adding Angle of fireworks explosion object particles in a random way of 360 degrees

Public class ParticleFireworksExplosion {private float [] mDirectionVector = {0 f, 0 f, 0.5 f, 1 f}; 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); }}Copy the code

2.2 and then used in the Render ParticleFireworksExplosion as the particle emitters

public class ParticlesRender implements GLSurfaceView.Renderer { ... private ParticleFireworksExplosion particleFireworksExplosion; @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { ... particleFireworksExplosion = new ParticleFireworksExplosion(); } @Override public void onDrawFrame(GL10 gl) { ... . / / / / particle emitter add particles mParticleShooter addParticles (mParticleSystem, curTime, 20); int color = Color.rgb(255, 50, 5); / / blast particle generator added particle particleFireworksExplosion addExplosion (mParticleSystem, new Geometry. The Point (0, 0 f, 0), color, curTime); . }Copy the code

The effect is as follows:

Problem 1: This is clearly not a firework explosion

A firework explosion is a single explosion at a time, and then the firework particles expand outward in a circle. The current effect is to emit new particles all the time.

To do this, the particles need to be fired at an interval of time in the onDrawFrame, so that the “fireworks fly for a while” to form the fireworks explosion effect; At the same time, in order to maintain the same number of particles at the same time, we have to emit particles at the same time. The concrete implementation is as follows:

public class ParticleFireworksExplosion { ... private final int mPreAddParticleCount = 100; public void addExplosion(ParticleSystem particleSystem, Geometry.Point position, int color, Float curTime) {// Instead of OnDrawFrame, add fireworks explosion particles, use 1/100 sampling rate, let particles fly for a while, If (mrandom.nextfloat () < 1.0f/mPreAddParticleCount) {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); }}}}Copy the code

The effect is as follows:

Problem 2: The effect of fireworks diffusion is not circular but elliptical

This requires projection matrix and view matrix transformation to project the ellipse onto the screen.

So that’s what we need to do

1. Add uniFROM mat4 to the vertex shader, and the assignment to gl_Position needs to be multiplied by the matrix. 3. Define and calculate perspective matrix and attempt matrix in Render, and generate matrix dataCopy the code

The concrete implementation is as follows:

1. Vertex shaders

uniform float u_Time; uniform mat4 u_Matrix; // Define the matrix data type variable 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; // Particle duration Current time - Start time v_ElapsedTime = u_Time - a_PatricleStartTime; Float gravityFactor = v_ElapsedTime * v_ElapsedTime / 9.8; float gravityFactor = v_ElapsedTime * v_ElapsedTime / 9.8; Vec3 curPossition = a_Position + (a_Direction * v_ElapsedTime); vec3 curPossition = a_Position + (a_Direction * v_ElapsedTime); // Subtract the effect of gravity or drag. Y -= gravityFactor; // Pass the current position to the chip shader via the built-in variable. / / gl_Position = vec4 (curPossition, 1.0); // Comment out the implementation and change it to the implementation below. Gl_Position = u_Matrix * VEC4 (curPossition, 1.0); Gl_PointSize = 25.0; }Copy the code

2. Parse and assign matrix in Program

public class ParticleShaderProgram { ... private final String U_MATRIX = "u_Matrix"; private final int uMatrixLocation; public ParticleShaderProgram(Context context) { ... UMatrixLocation = glGetUniformLocation(program, U_MATRIX); . Public void setimaginative (float[] array, float curTime, public void setimaginative (float[] array, float curTime, int textureId){ GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0); . }}Copy the code

3. Define and calculate perspective matrix and attempt matrix in Render, and generate matrix data

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]; @override public 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); } @Override public void onDrawFrame(GL10 gl) { ... / / set Uniform variable mProgram. SetUniforms (viewProjectionMatrix, curTime mTextureId); }}Copy the code

The effect is as follows:

Question 3, the present fireworks are red, how to achieve colorful fireworks?

We only need to modify the color of the particle. We randomly adjust the tone through HSV color space, and then convert it to the color value of RGB color space and assign it to the particle. The specific implementation is as follows

Public class ParticleFireworksExplosion {private float [] mDirectionVector = {0 f, 0 f, 0.3 f, 1 f}; private float[] mResultVector = new float[4]; private final Random mRandom = new Random(); private float[] mRotationMatrix = new float[16]; private final int mPreAddParticleCount = 100; Private final Float [] HSV = {0f, 1f, 1f} private final float[] HSV = {0f, 1f, 1f}; public void addExplosion(ParticleSystem particleSystem, Geometry.Point position, Float curTime) {// Instead of OnDrawFrame, add fireworks explosion particles, use 1/100 sampling rate, let particles fly for a while, If (mrandom.nextfloat () < 1.0f/mPreAddParticleCount) {HSV [0] = random.nextint (360); Int color = color.hsvTocolor (HSV); int color = color.hsvTocolor (HSV); // Add 100*3 directions 360 random particles at the same time 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, the new Geometry. The Vector (mResultVector [0], mResultVector [1] + 0.3 f, / / due to the inertia YanHuaDan upward, Add an upward offset to the explosion to make it look more realistic. mResultVector[2]), curTime); }}}}Copy the code

The effect is just as shown in the opening paragraph

The full code has been uploaded to Github

data

OpenGL ES 3.0 Programming Guide OpenGL ES Application Development Practice Guide

[Android super powerful particle animation library, meteor shower, explosion, full screen flying flowers, [OpenGL advanced (6)- particle system] [OpenGL] Shader instance analysis (7)- snow falling effect]

harvest

Through the study and practice of OpenGL ES particle system, we found that many gorgeous effects can be made through particles. In the process of learning and practicing, I find more and more that there is still a long way to go, and it is necessary to keep learning and practicing.

1. Analyze the scene and characteristics of fireworks explosion

2. Gradually realize colorful fireworks effect through practice 3. Solve problems encountered

Thank you for reading

Originally, I planned to write 2-3 OpenGL ES series, and gradually learn and practice sky box and lighting, but I feel that the application scenes and overall direction are not very relevant at present. So prepare to enlarge the follow-up links of learning practice. In the next article, we will start the JNI and NDK series of learning practices. Welcome to pay attention to the public account “audio and video development journey”, learn and grow together.

Welcome to communicate