你的位置:首页 > 操作系统

[操作系统]Android OpenGL ES 3.0 纹理应用


本文主要演示OpenGL ES 3.0 纹理演示。接口大部分和2.0没什么区别,脚本稍微有了点变化而已。

扩展GLSurfaceView

package com.example.gles300;import android.app.ActivityManager;import android.content.Context;import android.content.pm.ConfigurationInfo;import android.opengl.GLSurfaceView;import android.util.AttributeSet;import android.util.Log;/** * * @author gaofeng * */public class MyGLSurfaceView extends GLSurfaceView {		private GLRenderer renderer;	/**	 * @param context	 */	public MyGLSurfaceView(Context context) {		super(context);		init();	}	/**	 * @param context	 * @param attrs	 */	public MyGLSurfaceView(Context context, AttributeSet attrs) {		super(context, attrs);		init();	}		private void init() {		ActivityManager am = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);		ConfigurationInfo info = am.getDeviceConfigurationInfo();		String v = info.getGlEsVersion(); //判断是否为3.0 ,一般4.4就开始支持3.0版本了。		if (v.equalsIgnoreCase("3.0")) {			setEGLContextClientVersion(3);		} else {			setEGLContextClientVersion(2);		}		renderer = new GLRenderer();		renderer.setContext(getContext());		setRenderer(renderer);		setRenderMode(RENDERMODE_CONTINUOUSLY);	}}

  

package com.example.gles300;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.GLES30;import android.opengl.GLSurfaceView.Renderer;import android.opengl.GLUtils;import android.opengl.Matrix;import android.util.Log;/** * @author gaofeng * */public class GLRenderer implements Renderer {		   public static float[] projMatrix = new float[16];// 投影   public static float[] viewMatrix = new float[16];// 相机   public static float[] mViewPjMatrix;// 总变换矩阵   public static float[] matrixs = new float[16];   public static int textureId = -1;   Context context;   MyDrawModel drawModel; 	public void setContext(Context context) {		this.context = context;	}		public GLRenderer() {	}	 @Override 	  public void onDrawFrame(GL10 arg0) { 	    GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT); 	    Log.e("", "textureId:" + textureId); 	    drawModel.drawFrame(textureId); 	  } 	 	  @Override 	  public void onSurfaceChanged(GL10 arg0, int w, int h) { 	    GLES30.glViewport(0, 0, w, h); 	    float ratio = (float) w / h; 	    Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 1, 10);//投影矩阵设置 	    Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0, 0, 0, 0.0f, 1.0f, 0.0f);//摄像机坐标设置 	  } 	 	  @Override 	  public void onSurfaceCreated(GL10 g, EGLConfig eglConfig) { 	    GLES30.glClearColor(0.5f,0.5f,0.5f, 1.0f);  	    GLES30.glEnable(GLES30.GL_DEPTH_TEST); 	    InputStream ins = null; 	    drawModel = new MyDrawModel(); 	    drawModel.init(); 	    try { 	      ins = context.getAssets().open("girl4.jpg"); 	      textureId = createTexture(ins); 	      Log.e("", "textureId:" + textureId); 	    } catch (IOException e) { 	      e.printStackTrace(); 	    } finally { 	      try { 	      	if (ins != null) {	      		ins.close(); 	      	}	      } catch (IOException e) { 	        e.printStackTrace(); 	      } 	    } 	    GLES30.glDisable(GLES30.GL_CULL_FACE); 	  } 	  	  public static int createTexture(InputStream ins) { 	    int[] textures = new int[1]; 	    GLES30.glGenTextures(1, textures, 0);	    int textureId = textures[0]; 	    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId); 	    GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER,GLES30.GL_NEAREST);  	    GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_MAG_FILTER,GLES30.GL_LINEAR); 	    GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S,GLES30.GL_CLAMP_TO_EDGE); 	    GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T,GLES30.GL_CLAMP_TO_EDGE); 	    //上面是纹理贴图的取样方式,包括拉伸方式,取临近值和线性值 	    Bitmap bitmap = BitmapFactory.decodeStream(ins); 	    GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);//让图片和纹理关联起来,加载到OpenGl空间中 	    Log.d("OPENGL","bitmap:" + bitmap); 	    bitmap.recycle();//不需要,可以释放 	    return textureId; 	  } }

  

package com.example.gles300;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import android.opengl.GLES30;import android.opengl.Matrix;import android.util.Log;/** * @author gaofeng * */public class MyDrawModel {  
private int programId; private int mVPMatrixHandle; private FloatBuffer vertexBuffer; private FloatBuffer texCoorBuffer; public MyDrawModel() { } public void init() { initData(); int vertexsharder = GLHelper.compileScript(GLES30.GL_VERTEX_SHADER, GLScript.vertex3); int fragmentsharder = GLHelper.compileScript(GLES30.GL_FRAGMENT_SHADER, GLScript.fragment3); programId = GLHelper.linkAttach(vertexsharder, fragmentsharder); boolean isOK = GLHelper.checkProgram(programId); mVPMatrixHandle = GLES30.glGetUniformLocation(programId, "uMVPMatrix"); } private void initData() { //X,Y,Z 顶点 float vertices[] = new float[] { 0, 0, 0, -1.8f, -1f, 0, 1.8f, -1f, 0, 1.8f, 1f, 0, -1.8f, 1f, 0, -1.8f, -1f, 0 }; ByteBuffer vb = ByteBuffer.allocateDirect(vertices.length * 4); vb.order(ByteOrder.nativeOrder()); vertexBuffer = vb.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); //纹理空间坐标UV float texCoor[] = new float[] { 0.5f, 0.5f, 0f, 1f, 1f, 1f, 1f, 0f, 0f, 0f, 0f, 1f }; ByteBuffer cb = ByteBuffer.allocateDirect(texCoor.length * 4); cb.order(ByteOrder.nativeOrder()); texCoorBuffer = cb.asFloatBuffer(); texCoorBuffer.put(texCoor); texCoorBuffer.position(0); } public void drawFrame(int textureId) { GLES30.glUseProgram(programId); // // 初始化矩阵 Matrix.setRotateM(GLRenderer.matrixs, 0, 0, 1, 0, 0); Matrix.translateM(GLRenderer.matrixs, 0, 0, 0, 1); //矩阵转换 ,投影矩阵,摄像机矩阵,模型矩阵 GLRenderer.mViewPjMatrix = new float[16]; Matrix.multiplyMM(GLRenderer.mViewPjMatrix, 0, GLRenderer.viewMatrix,0, GLRenderer.matrixs, 0); Matrix.multiplyMM(GLRenderer.mViewPjMatrix, 0, GLRenderer.projMatrix,0, GLRenderer.mViewPjMatrix, 0); GLES30.glUniformMatrix4fv(mVPMatrixHandle, 1, false, GLRenderer.mViewPjMatrix, 0); GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 3 * 4, vertexBuffer); GLES30.glVertexAttribPointer(1, 2, GLES30.GL_FLOAT, false, 2 * 4, texCoorBuffer); GLES30.glEnableVertexAttribArray(0); GLES30.glEnableVertexAttribArray(1); GLES30.glActiveTexture(GLES30.GL_TEXTURE0); GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId); GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, 6);//六个定点,绘制三角形 } }

  

package com.example.gles300;/** * @author gaofeng * */public class GLScript {	   public GLScript() {   }     public static final String vertex3 =  		"#version 300 es \n" +  		"uniform mat4 uMVPMatrix;\n"       + "layout(location = 0) in vec3 aPosition;\n"       + "layout(location = 1) in vec2 aTexCoor;\n"       + "out vec2 vTextureCoord;\n"        + "void main() { \n"       + "gl_Position = uMVPMatrix * vec4(aPosition,1);\n"       + "vTextureCoord = aTexCoor;\n"        + "}\n"       ;     public static final String fragment3 = "#version 300 es \n" + 		  	"precision mediump float;\n"       + "in vec2 vTextureCoord;\n"       + "uniform sampler2D sTexture;\n"       + "out vec4 v_color;\n"      + "void main() { \n"       + "vec2 coord = vTextureCoord;\n"       + "coord.s = coord.s * 0.5;\n"      + "v_color = texture(sTexture, coord); \n"       + "}\n"       ; }

  layout(location=0) in vec3 aPosition;定义个输入,location定义了这个数据的位置,相对于2.0 不需要进行attribute查找。

     3.0中内置变量gl_FragColor 也被 out 颜色输出修改了。

     3.0脚本前面需要添加 #version 300 es 版本声明

 

最后是脚本编译和链接工具类.

package com.example.gles300;import android.opengl.GLES30;import android.util.Log;/** * @author gaofeng * */public class GLHelper {	/**	 * 	 */	public GLHelper() {		// TODO Auto-generated constructor stub	}		public static int linkGL(){ 	  int programId = GLES30.glCreateProgram();//创建一个程序 	  if (programId == 0) { 	    Log.e("OPENGL", "Error Create Link Program"); 	    return 0; 	  } 	  return programId; 	} 	 	public static int linkAttach(int vertexsharder,int fragmentsharder){ 	  int programId = linkGL(); 	  GLES30.glAttachShader(programId, vertexsharder); //和着色器进行关联 	  GLES30.glAttachShader(programId, fragmentsharder);//和着色器进行关联 	  GLES30.glLinkProgram(programId); //把program链接起来 	  int status[] = new int[1]; 	  GLES30.glGetProgramiv(programId, GLES30.GL_LINK_STATUS, status, 0); //这地方一样是检查是否有错误发生。 	  Log.d("OPENGL","linkAttach link status is " + GLES30.glGetProgramInfoLog(programId)); 	  if (status[0] == 0) { 	    Log.e("OPENGL","link status is error."); 	    GLES30.glDeleteProgram(programId); 	    return 0; 	  } 	  return programId; 	} 		public static boolean checkProgram(int programId){ 	  GLES30.glValidateProgram(programId); 	  int status[] = new int[1]; 	  GLES30.glGetProgramiv(programId,GLES30.GL_VALIDATE_STATUS, status,0); 	  if (status[0] == 0) { 	    Log.e("OPENGL","program is error"); 	    return false; 	  } 	  return true; 	} 		public static int compileScript(int type, String script){ 	  int objID = GLES30.glCreateShader(type); //创建一个着色器对象,TYPE表示顶点着色器和片段着色器 	  if (objID == 0) { //0表示有错误 	    return 0; 	  } 	  GLES30.glShaderSource(objID, script); //把脚本代码传给OpenGL 引擎 	  GLES30.glCompileShader(objID); //开始编译 	  int[] status = new int[1]; 	  GLES30.glGetShaderiv(objID, GLES30.GL_COMPILE_STATUS, status, 0); //看看编译结果是否有错误。 	  Log.d("OPENGL","compileScript status info:" + GLES30.glGetShaderInfoLog(objID)); 	  if (status[0] == 0) { 	    GLES30.glDeleteShader(objID);//有错误我们删除这个对象。 	    Log.e("OPENGL", "Error Compile Script:" + script); 	    return 0; 	  } 	  return objID; 	} }