本文主要演示OpenGL ES 3.0 紋理演示。接口大部分和2.0沒什麼區別,腳本稍微有了點變化而已。java
擴展GLSurfaceViewandroid
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查找。app
3.0中內置變量gl_FragColor 也被 out 顏色輸出修改了。ide
3.0腳本前面須要添加 #version 300 es 版本聲明工具
最後是腳本編譯和連接工具類.this
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; } }