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;  
	}  
}

 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号