雾的实现以及Opengl的数组存储与java不同的工具包BufferUtil的实现
一、雾和流动红旗的形成,Render类如下:
package com.example.user.flagdemo; import android.graphics.Bitmap;import android.opengl.GLSurfaceView;import android.opengl.GLUtils; import java.nio.FloatBuffer;import java.nio.IntBuffer; import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10; /** * Created by user on 2016/9/14. */public class GLRendererfog implements GLSurfaceView.Renderer { int textureSize = 2; int texture[] = new int [textureSize]; private Bitmap mBitmap[]; Point [][] points = new Point[45][45]; private int wiggle_count=0; //设置雾的属性参数 int fogMode[]= { GL10.GL_EXP, GL10.GL_EXP2, GL10.GL_LINEAR }; // 雾气的模式 int fogfilter= 1; // 使用哪一种雾气 float fogColor[]= {0.5f, 0.5f, 0.0f, 1.0f}; // 雾的颜色设为白色 public GLRendererfog(Bitmap mBitmap[]) { this.mBitmap = mBitmap; } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 黑色背景 gl.glClearColor(0, 0, 0, 0); // 启用阴影平滑 gl.glShadeModel(GL10.GL_SMOOTH); // 启用深度测试 gl.glEnable(GL10.GL_DEPTH_TEST); gl.glFogx(GL10.GL_FOG_MODE, fogMode[fogfilter]); // 设置雾气的模式 gl.glFogfv(GL10.GL_FOG_COLOR, fogColor,0); // 设置雾的颜色 gl.glFogf(GL10.GL_FOG_DENSITY, 0.1f); // 设置雾的密度 gl.glHint(GL10.GL_FOG_HINT, GL10.GL_DONT_CARE); // 设置系统如何计算雾气 gl.glFogf(GL10.GL_FOG_START, 1.0f); // 雾气的开始位置 gl.glFogf(GL10.GL_FOG_END, 5.0f); // 雾气的结束位置 gl.glEnable(GL10.GL_FOG); // 使用雾气 // 启用混合模式 gl.glEnable(GL10.GL_BLEND); gl.glDisable(GL10.GL_DEPTH_TEST); // 关闭深度测试 //设置光线,,1.0f为全光线,a=50% gl.glColor4f(1.0f,1.0f,1.0f,0.5f); // 基于源象素alpha通道值的半透明混合函数 gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE); //启用纹理映射 gl.glClearDepthf(1.0f); //深度测试的类型 gl.glDepthFunc(GL10.GL_LEQUAL); //精细的透视修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); //允许2D贴图,纹理 gl.glEnable(GL10.GL_TEXTURE_2D); getTextures(gl); getPoints(); // //设置光颜色// FloatBuffer lightAmbient = BufferUtil.floatToBuffer(new float[]{// 1f, 1f, 1f, 1f// } );// FloatBuffer lightDiffuse = BufferUtil.floatToBuffer(new float[]{// 1f,1f,1f,1f// } );// //定义光源位置// FloatBuffer lightPosition = BufferUtil.floatToBuffer(new float[]{// -2f,0f,-4f,1f// } );////// //设置环境光// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient);//// //设置漫射光// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse);//// //设置光源位置// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition);//// //开启一号光源// gl.glEnable(GL10.GL_LIGHT1); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { float ratio = (float) width / height; //设置OpenGL场景的大小 gl.glViewport(0, 0, width, height); //设置投影矩阵 gl.glMatrixMode(GL10.GL_PROJECTION); //重置投影矩阵 gl.glLoadIdentity(); // 设置视口的大小 gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); // 选择模型观察矩阵 gl.glMatrixMode(GL10.GL_MODELVIEW); // 重置模型观察矩阵 gl.glLoadIdentity(); } @Override public void onDrawFrame(GL10 gl) { // 清除屏幕和深度缓存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 重置当前的模型观察矩阵// gl.glEnable(GL10.GL_LIGHTING); gl.glLoadIdentity(); gl.glTranslatef(0f , 0f , -9f); FloatBuffer texCoords2 = BufferUtil.getFloatBuffer(8); FloatBuffer vertices2 = BufferUtil.getFloatBuffer(12);; gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//启用纹理映射 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); for (int x = 0; x < 44; x++){ for (int y = 0; y < 44; y++) { //文理映射,每个点在纹理中的映射位置,文理的大小为1f float float_x = (float) (x) / 44.0f; //生成 x 浮点值 float float_y = (float) (y) / 44.0f; //生成 Y 浮点位 float float_xb = (float) (x + 1) / 44.0f; // x 浮点值+0.0227f float float_yb = (float) (y + 1) / 44.0f; // Y 浮点值+0.0227f vertices2.clear(); vertices2.put(points[x][y].x); vertices2.put(points[x][y].y); vertices2.put(points[x][y].z); vertices2.put(points[x][y + 1].x); vertices2.put( points[x][y + 1].y); vertices2.put( points[x][y + 1].z); vertices2.put( points[x + 1][y + 1].x); vertices2.put(points[x + 1][y + 1].y); vertices2.put(points[x + 1][y + 1].z); vertices2.put( points[x + 1][y].x); vertices2.put( points[x + 1][y].y); vertices2.put( points[x + 1][y].z); //position是当前访问位置,因此每次put后position都是指向存储的位置的,绘图点映射必须从头开始的 vertices2.position(0); texCoords2.clear(); texCoords2.put(float_x); texCoords2.put(1 - float_y); texCoords2.put(float_x); texCoords2.put(1 - float_yb); texCoords2.put( float_xb); texCoords2.put( 1 - float_yb); texCoords2.put( float_xb); texCoords2.put( 1 - float_y); texCoords2.position(0); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices2); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoords2); gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4); } } wiggle_count++; gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);//两帧渲染一次,正弦改变z坐标的值让红旗飘动
float hold; if(wiggle_count == 2) { for( int y = 0; y < 45; y++ )//沿 Y 平面循环 { hold = points[0][y].z; //存储当前左侧波浪值 for (int x = 0; x < 44; x++)// 沿 x 乎面循环 { // 当前波浪值等于其右侧的波浪值 points[x][y].z = points[x + 1][y].z; } points[44][y].z = hold; //刚才的位成为最左侧的波浪值 wiggle_count = 0; //计数器清零 } wiggle_count = 0; } } private void getTextures(GL10 gl) { IntBuffer intBuffer = IntBuffer.allocate(2);//申请2个纹理存储空间 // 创建纹理 gl.glGenTextures(2 , intBuffer); //创建2个纹理,绑定intuffer texture[0] = intBuffer.get(); // 获取第一个纹理的存储指针,即纹理存储位置,位置+1 texture[1] = intBuffer.get(); //获取下一个纹理存储的位置 // 设置要使用的纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); //生成纹理 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[0] , 0);//利用图mBitmap[0]生成纹理,存储在texture[0] // 线形滤波 gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); //生成第二个纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[1] , 0);//利用图mBitmap[0]生成纹理,存储在texture[1] gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); } public Point getPoint(int x,int y) { float x1=( (float)x/5.0f) -4.5f ; float y1= ( ((float)y/5.0f)- 4.5f ); float z1 = (float) (Math.sin(((((float)x/5.0f) *40.0f)/360.0f)* 3.141592654*2.0f)); return new Point(x1,y1,z1); } public void getPoints() { for (int x = 0; x < 45; x++) for (int y = 0; y < 45; y++) { points[x][y] = getPoint( x, y); } }}notice:1、正弦改变z的坐标来实现红旗飘动的。
2、当向buffer里put值时候,position的值就会自动加1,因此当存完了buffer里的值时候要将position置为0,让绘图的时候可以读取所有的点信息
二、将java数组或者缓冲区转化为opengl的存储方式的工具类:
package com.example.user.flagdemo; import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import java.nio.IntBuffer; /** * Created by lenovo on 2016/9/6. */public class BufferUtil { public static FloatBuffer floatToBuffer(float[] a) { //先初始化buffer,数组的长度*4,因为一个float占4个字节 ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4); //数组排序用nativeOrder,根据本地的排列顺序,指定存储方式,是1. Little endian(小头):将低序字节存储在起始地址 // 2. Big endian(大头):将高序字节存储在起始地址 mbb.order(ByteOrder.nativeOrder()); FloatBuffer mBuffer = mbb.asFloatBuffer(); mBuffer.put(a); mBuffer.position(0); return mBuffer; } // 将数组a转化为intbuffer public static IntBuffer intToBuffer(int[] a) { //先初始化buffer,数组的长度*4,因为一个float占4个字节 ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4); //数组排序用nativeOrder mbb.order(ByteOrder.nativeOrder()); IntBuffer mBuffer2 = mbb.asIntBuffer(); mBuffer2.put(a); mBuffer2.position(0); return mBuffer2; } public static FloatBuffer getFloatBuffer(int length) { ByteBuffer mbb = ByteBuffer.allocateDirect(length * 4); mbb.order(ByteOrder.nativeOrder()); FloatBuffer mBuffer = mbb.asFloatBuffer(); mBuffer.position(0); return mBuffer; } public static IntBuffer getIntBuffer(int length) { ByteBuffer mbb = ByteBuffer.allocateDirect(length * 4); mbb.order(ByteOrder.nativeOrder()); IntBuffer mBuffer = mbb.asIntBuffer(); mBuffer.position(0); return mBuffer; } } class Point{ float x; float y; float z; public Point(float x, float y , float z) { this.x=x; this.y=y; this.z=z; } } 前面2个方法是将java的float和int数组转化为对应的opengl存储方式的缓冲区,后面的2个方法是定义相对应的一定长度的opengl存储的对应的缓冲区。
浙公网安备 33010602011771号