做一个飘动的旗帜效果,思路大概为:将旗形的波浪分割成很小的四边形,然后多少时间进行刷新,Z方向上运用sin函数改变,看起来有飘动的感觉
实例代码如下:
1、准备图片资源 : initBitmap类
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class initBitmap {
public static Bitmap bitmap;
public static void init(Resources res){
bitmap = BitmapFactory.decodeResource(res, R.drawable.flag) ; //图片
}
}
2、Activity类
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class FlagOpenGLActivity extends Activity {
GLSurfaceView glView;
FlagRender flagRender = new FlagRender();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initBitmap.init(this.getResources());
glView = new GLSurfaceView(this);
glView.setRenderer(flagRender);
setContentView(glView);
}
}
3、渲染类
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
public class FlagRender implements Renderer {
/**
* 制作飘动的旗帜效果
*/
private float[] texVertices = new float[12];
FloatBuffer texBuffer;
private float[] coord = new float[8];
FloatBuffer coordBuffer;
private int[] textures = new int[1];
float vertex[][][] = new float[45][45][3];// 网格顶点数组
int wiggle_count = 0; // 指定旗型波浪的运行速度
float hold; // 临时变量
float xrot, yrot, zrot; // 各轴旋转
/**
* 初始化缓冲数据
*/
public void init() {
ByteBuffer bb = ByteBuffer.allocateDirect(texVertices.length * 4);
bb.order(ByteOrder.nativeOrder());
texBuffer = bb.asFloatBuffer();
texBuffer.put(texVertices);
texBuffer.position(0);
//
ByteBuffer coordbb = ByteBuffer.allocateDirect(coord.length * 4);
coordbb.order(ByteOrder.nativeOrder());
coordBuffer = coordbb.asFloatBuffer();
coordBuffer.put(coord);
coordBuffer.position(0);
}
@Override
public void onDrawFrame(GL10 gl) {
init();// 初始化
int x, y;
float f_x, f_y, f_xb, f_yb; // 用来将旗形的波浪分割成很小的四边形
//
gl.glClear(GL10.GL_DEPTH_BUFFER_BIT | GL10.GL_COLOR_BUFFER_BIT);
gl.glLoadIdentity();
//
gl.glTranslatef(0.0f, 0.0f, -12.0f);// 往里缩12单位
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);// 绕X轴旋转
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);// 绕Y轴旋转
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);// 绕Z轴旋转
//
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, texBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, coordBuffer);
// gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// 四边形绘制开始
for (x = 0; x < 44; x++) {
for (y = 0; y < 44; y++) {
f_x = (float) x / 44.0f; // 生成X的浮点数
f_y = (float) y / 44.0f;// 生成Y的浮点数
f_xb = (float) (x + 1) / 44.0f; // X浮点值+0.0227f
f_yb = (float) (y + 1) / 44.0f;// Y浮点值+0.0227f
//
coordBuffer.clear();
// 左下角
coordBuffer.put(f_x);
coordBuffer.put(f_y);
// 左上角
coordBuffer.put(f_x);
coordBuffer.put(f_yb);
// 右上角
coordBuffer.put(f_xb);
coordBuffer.put(f_yb);
// 右下角
coordBuffer.put(f_xb);
coordBuffer.put(f_y);
//
// 左下角
texBuffer.clear();
texBuffer.put(vertex[x][y][0]);
texBuffer.put(vertex[x][y][1]);
texBuffer.put(vertex[x][y][2]);
// 左上角
texBuffer.put(vertex[x][y + 1][0]);
texBuffer.put(vertex[x][y + 1][1]);
texBuffer.put(vertex[x][y + 1][2]);
// 右上角
texBuffer.put(vertex[x + 1][y + 1][0]);
texBuffer.put(vertex[x + 1][y + 1][1]);
texBuffer.put(vertex[x + 1][y + 1][2]);
// 右下角
texBuffer.put(vertex[x + 1][y][0]);
texBuffer.put(vertex[x + 1][y][1]);
texBuffer.put(vertex[x + 1][y][2]);
//注意:如果设为GL10.GL_TRIANGLE_STRIP模式的话,会产生黑点点,不好看
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);
}
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
/**
* 每绘制两次场景,循环一次sin值,以产生运动效果。 用来降低波浪速度(每隔2帧一次)
*/
if (wiggle_count == 2) { // 沿着Y 平面循环
for (y = 0; y < 45; y++) {
hold = vertex[0][y][2];
for (x = 0; x < 44; x++) {
// 当前波浪值等于其右侧的波浪值
vertex[x][y][2] = vertex[x + 1][y][2]; //
}
vertex[44][y][2] = hold; // 刚才的值成为最左侧的波浪值
}
wiggle_count = 0;// 清零
}
wiggle_count++;// 加一
xrot += 0.3f;
yrot += 0.2f;
zrot += 0.4f;
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 15);
// 设置观察模型
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
// 黑色背景色
gl.glClearColorx(0, 0, 0, 0);
// 启用阴影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
// 深度测试类型
gl.glDepthFunc(GL10.GL_LEQUAL);
// 设置深度缓存
gl.glClearDepthf(1.0f);
// 启用纹理
gl.glEnable(GL10.GL_TEXTURE_2D);
// 生成纹理
gl.glGenTextures(1, textures, 0);
// 绑定纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, initBitmap.bitmap, 0);
//线性滤波
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
/**
*
*/
// 沿X平面循环
for (int x = 0; x < 45; x++) {
// 沿Y平面循环
for (int y = 0; y < 45; y++) {
// 向表面添加波浪效果
vertex[x][y][0] = (float) ((x / 5.0f) - 4.5f);
vertex[x][y][1] = (float) ((y / 5.0f) - 4.5f);
// 2 *pai* r 角度
vertex[x][y][2] = (float) (Math
.sin(((((float) x / 5.0f) * 40.0f) / 360.0f) * 3.141592654 * 2.0f));
}
}
}
}
4、运行效果: