效果图:
编写dad.java文件
*声明三个矩形,分别贴s,t的最大值为1X1、4X4、4X2的纹理涂,在场景中分别绘制1X1、4X4、4X2的纹理矩形
*设置视窗的大小、矩阵类型、并设置投影模式为透视投影
*定义封装方法initTexture()以获取纹理ID,该方法通过收取图片ID,生成一个纹理ID并返回
package com.scout.eeeeeee; /** * Created by liuguodong on 2017/10/28. */ import java.io.IOException; import java.io.InputStream; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLSurfaceView; import android.opengl.GLUtils; public class dad extends GLSurfaceView{ private SceneRenderer mRenderer;//定义场景渲染器 public dad(Context context) { super(context); mRenderer = new SceneRenderer(); //创建渲染器 setRenderer(mRenderer); //设置渲染器 setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置主动渲染模式 } private class SceneRenderer implements GLSurfaceView.Renderer { int testTexId;//纹理 laCH trOneXOne;//1*1贴图矩形 laCH trFourXFour;//4*4贴图矩形 laCH trFourXTwo;//4*2贴图矩形 public void onDrawFrame(GL10 gl) { //打开背面剪裁 gl.glEnable(GL10.GL_CULL_FACE); //着色模型为平滑着色 gl.glShadeModel(GL10.GL_SMOOTH); //清除颜色缓存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //模式矩阵 gl.glMatrixMode(GL10.GL_MODELVIEW); //单位矩阵 gl.glLoadIdentity(); //推远场景 gl.glTranslatef(0, 0, -3); //绘制1*1纹理矩形 gl.glPushMatrix(); gl.glTranslatef(-3.5f, 0, 0); trOneXOne.drawSelf(gl); gl.glPopMatrix(); //绘制4*4纹理矩形 gl.glPushMatrix(); gl.glTranslatef(0, 0, 0); trFourXFour.drawSelf(gl); gl.glPopMatrix(); //绘制4*4纹理矩形 gl.glPushMatrix(); gl.glTranslatef(3.5f, 0, 0); trFourXTwo.drawSelf(gl); gl.glPopMatrix(); } public void onSurfaceChanged(GL10 gl, int width, int height) { //视窗大小及位置 gl.glViewport(0, 0, width, height); //设置为为投影矩阵 gl.glMatrixMode(GL10.GL_PROJECTION); //设置为单位矩阵 gl.glLoadIdentity(); //获取透视投影的比例 float ratio = (float) width / height; //计算产生透视投影矩阵 gl.glFrustumf(-ratio, ratio, -1, 1, 1, 100); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { //抗抖动 关闭 gl.glDisable(GL10.GL_DITHER); //设置使用快速模式 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST); //设置屏幕背景色黑色RGBA gl.glClearColor(0,0,0,0); //深度测试 gl.glEnable(GL10.GL_DEPTH_TEST); //纹理初始化 testTexId=initTexture(gl,R.drawable.lashen); //创建纹理矩形 trOneXOne=new laCH(1.5f,1.5f,testTexId,1,1);//s-t 0-1 trFourXFour=new laCH(1.5f,1.5f,testTexId,4,4);//s-t 4-4 trFourXTwo=new laCH(1.5f,1.5f,testTexId,4,2);//s-t 4-2 } } //初始化纹理 public int initTexture(GL10 gl,int drawableId)//textureId { //生成纹理ID int[] textures = new int[1]; gl.glGenTextures(1, textures, 0); int currTextureId=textures[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); //设置纹理拉伸方式为重复 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT); InputStream is = this.getResources().openRawResource(drawableId); Bitmap bitmapTmp; try { bitmapTmp = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch(IOException e) { e.printStackTrace(); } } GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0); bitmapTmp.recycle(); return currTextureId; } }
编写laCH
*初始化顶点坐标数据,冰川件顶点坐标数据缓冲
*定义方法drawSelf()来开启纹理以绘制图形
package com.scout.eeeeeee; /** * Created by liuguodong on 2017/10/29. */ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; public class laCH { private FloatBuffer mVertexBuffer;//缓冲顶点坐标 private FloatBuffer mTextureBuffer;//缓冲顶点纹理 int vCount=0; int texId; public laCH(float width,float height,int texId,float sRange,float tRange) { this.texId=texId; //开始初始化顶点坐标数据 vCount=6; final float UNIT_SIZE=1.0f; float vertices[]=new float[] { width*UNIT_SIZE,height*UNIT_SIZE,0, -width*UNIT_SIZE,height*UNIT_SIZE,0, -width*UNIT_SIZE,-height*UNIT_SIZE,0, -width*UNIT_SIZE,-height*UNIT_SIZE,0, width*UNIT_SIZE,-height*UNIT_SIZE,0, width*UNIT_SIZE,height*UNIT_SIZE,0, }; //创建顶点坐标数据缓冲 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); vbb.order(ByteOrder.nativeOrder());//字节顺序 mVertexBuffer = vbb.asFloatBuffer();//转为Float型 mVertexBuffer.put(vertices);//在缓冲区中放入顶点坐标数据 mVertexBuffer.position(0);//设置缓冲区起始位置 //初始化纹理 坐标 float[] texST= { sRange,0, 0,0, 0,tRange, 0,tRange, sRange,tRange, sRange,0 }; ByteBuffer tbb = ByteBuffer.allocateDirect(texST.length*4); tbb.order(ByteOrder.nativeOrder());//字节顺序 mTextureBuffer = tbb.asFloatBuffer();//转换为int型 mTextureBuffer.put(texST);//在缓冲区保存顶点着色数据 mTextureBuffer.position(0);//缓冲区的起始位置 } public void drawSelf(GL10 gl) { gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//启用顶点坐标数组 //设置画笔的顶点坐标 gl.glVertexPointer ( 3, GL10.GL_FLOAT, 0, mVertexBuffer ); //打开纹理 gl.glEnable(GL10.GL_TEXTURE_2D); //使用纹理ST坐标缓冲 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //用指定纹理设置画笔ST坐标 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer); //绑定当前纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texId); //绘制图形 gl.glDrawArrays ( GL10.GL_TRIANGLES, //用三角形方式填充 0, vCount ); } }
MyActivity.java
package com.scout.eeeeeee; import android.app.Activity; import android.os.Bundle; import android.app.Activity; import android.os.Bundle; import android.app.Activity; import android.os.Bundle; public class MyActivity extends Activity { /** Called when the activity is first created. */ private dad mGLSurfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGLSurfaceView = new dad(this); mGLSurfaceView.requestFocus();//获取焦点 mGLSurfaceView.setFocusableInTouchMode(true);//设置为可触控 setContentView(mGLSurfaceView); } @Override protected void onResume() { super.onResume(); mGLSurfaceView.onResume(); } @Override protected void onPause() { super.onPause(); mGLSurfaceView.onPause(); } }
注意:当在实现海洋或草原等较大纹理贴图时,使用纹理映射的拉伸方式既可以节省内存,又可以保证画面的真实性