刚学OpenGL 2个多星期,也算是入门了吧
在看了老外写的书 OpenGL ES 2 for Android A Quick - Start Guide.pdf
后,由于这本书上给的代码不够全,
自己功力太浅,对于一些了解有点疑惑,
费了差不多两天才调出想要的结果,下面就分享一下我的经历,若有问题,希望大家多多交流
本代码中包含的内容还是比较多的,使用OpenGL ES2.0编写,包含有顶点 shader和片段shader,
还包含了VBO(vertex buffer object),这里是我当时最疑惑的地方,因为对VBO的用法不熟悉,上网搜索了导致出不来结果,
后来还是在一个外国网站上找到答案的。
粒子系统是通过将时间作为一个变量绑定到绘制的点的位置信息中,由于时间是在流动的,因此粒子也会跟着在移动;从而就形成了粒子流,这里比较难理解
不废话了,直接上代码吧;
本程序代码结构:
先看MainActivity.java
package com.cxy.particles;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class MainActivity extends Activity {
GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView = new GLSurfaceView(this);
// 设置OpenGLES版本为2.0
glSurfaceView.setEGLContextClientVersion(2);
// 设置渲染器 渲染模式
MyRenderer mRenderer = new MyRenderer(this,glSurfaceView);
glSurfaceView.setRenderer(mRenderer);
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
// 显示渲染内容
setContentView(glSurfaceView);
}
}
最重要的渲染的文件MyRenderer.java
package com.cxy.particles;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Color;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
public class MyRenderer implements GLSurfaceView.Renderer {
GLSurfaceView glView;
private Context context;
//视图矩阵
private final float[] projectionMatrix=new float[16];
private final float[] viewMatrix=new float[16];
private final float[] viewProjectionMatrix=new float[16];
private ParticleShaderProgram particleProgram;
private ParticleSystem particleSystem;
private ParticleShooter redParticleShooter;
private ParticleShooter greenParticleShooter;
private ParticleShooter blueParticleShooter;
private long globalStartTime;
//private float globalStartTime;
public MyRenderer(Context context,GLSurfaceView view){
//保存上下文,个GLSurfaceView;
this.context=context;
this.glView = view;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//设置屏幕背景色
GLES20.glClearColor(0.0f,0.0f,0.0f,0.0f);
//获取GLSL脚本语言编译好后的programID
particleProgram=new ParticleShaderProgram(context,glView);
//获取粒子系统的实例,初始化粒子系统包含10000个粒子
particleSystem=new ParticleSystem(10000);
//获取系统时间
globalStartTime=System.nanoTime();
//globalStartTime = System.nanoTime()/1000000000f;
//设置粒子发射的方向,Y轴向上
final Vector3 particleDirection=new Vector3(0f,0.5f,0f);
//新建粒子发射器(红色粒子),获取实例
redParticleShooter=new ParticleShooter(
new Point3(-1f,0f,0f),
particleDirection,
Color.rgb(255,50,5));
//新建粒子发射器(绿色粒子),获取实例
greenParticleShooter=new ParticleShooter(
new Point3(0f,0f,0f),
particleDirection,
Color.rgb(25,255,25));
//新建粒子发射器(蓝色粒子),获取实例
blueParticleShooter=new ParticleShooter(
new Point3(1f,0f,0f),
particleDirection,
Color.rgb(5,50,255));
}
@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);
Matrix.setIdentityM(viewMatrix,0);
Matrix.translateM(viewMatrix,0,0f,-1.5f,-5f);
//设置最终的视点
Matrix.multiplyMM(
viewProjectionMatrix,
0,
projectionMatrix,
0,
viewMatrix,
0);
}
@Override
public void onDrawFrame(GL10 gl) {
//清除位缓存
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
float currentTime=(System.nanoTime()-globalStartTime)/1000000000f;
//float currentTime=(System.nanoTime()/1000000000f);
//Log.d("cxy", "CurrentTime = "+currentTime);
/*为粒子发射器添加粒子*/
redParticleShooter.addParticles(particleSystem,currentTime,5);
greenParticleShooter.addParticles(particleSystem,currentTime,5);
blueParticleShooter.addParticles(particleSystem,currentTime,5);
/*redParticleShooter.addParticles(particleSystem,globalStartTime,5);
greenParticleShooter.addParticles(particleSystem,globalStartTime,5);
blueParticleShooter.addParticles(particleSystem,globalStartTime,5);*/
//使用着色器绘制粒子,
particleProgram.useProgram();
//这是
particleProgram.setUniforms(viewProjectionMatrix,currentTime);
/**必须在USE progrem之后,才能进行数据绑定,即操作glVertexAttribPointer之类的函数
* bindData()将所有的数据:粒子顶点数据、颜色数据、方向数据、时间捆绑在一个VBO中,然后
* 通过这个VBO绘制的,
**/
particleSystem.bindData(particleProgram);
//绘制粒子
particleSystem.draw(particleProgram);
}
}