先上效果图
首先AndroidManifest.xml里声明版本:
<uses-feature android:glEsVersion="0x00030000" android:required="true" />然后在Acitivity里声明版本:
GLSurfaceView glSurfaceView = new GLSurfaceView(this); glSurfaceView.setEGLContextClientVersion(3); setContentView(glSurfaceView); glSurfaceView.setRenderer(new TriangleRenderer(this));
然后在Renderer的onSurfaceCreated回调里初始化顶点和颜色数据:
float[] triangleCoords = new float[] { 0.0f, 1, 0.0f, -1.0f, -1, 0.0f, 1.0f, -1, 0.0f }; mVertexBuffer = Utils.floatArray2FloatBuffer(triangleCoords); float[] color = new float[] { 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 }; mColorBuffer = Utils.floatArray2FloatBuffer(color); public static FloatBuffer floatArray2FloatBuffer(float[] array) { FloatBuffer floatBuffer = ByteBuffer.allocateDirect(array.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); floatBuffer.put(array).position(0); return floatBuffer; }并且创建program:
mProgram = Utils.createProgram(mContext, R.raw.triangle_v, R.raw.triangle_f); muMVPMatrixHandler = GLES30.glGetUniformLocation(mProgram, "uMVPMatrix"); mPosHandler = GLES30.glGetAttribLocation(mProgram, "aPosition"); mColorHandler = GLES30.glGetAttribLocation(mProgram, "aColor"); public static int createProgram(Context context, int vertextRawId, int fragmentRawId) { int vertexShader = loadShader(context, GL_VERTEX_SHADER, vertextRawId); if (vertexShader == 0) return 0; int fragmentShader = loadShader(context, GL_FRAGMENT_SHADER, fragmentRawId); if (fragmentShader == 0) return 0; int program = glCreateProgram(); if (program != 0) { glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); int[] linkStatus = new int[1]; glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0); if (linkStatus[0] != GL_TRUE) { Log.e(TAG, "createProgram : Cannot link program"); Log.e(TAG, "createProgram glError : " + glGetProgramInfoLog(program)); glDeleteProgram(program); program = 0; } } return program; } public static int loadShader(Context context, int type, int rawId) { String shaderCode = readStringFromInputStream(context.getResources().openRawResource(rawId)); return loadShader(type, shaderCode); } public static String readStringFromInputStream(InputStream inputStream) { InputStreamReader reader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(reader); StringBuilder builder = new StringBuilder(""); String str; try { while ((str = bufferedReader.readLine()) != null) { builder.append(str); builder.append("\n"); } } catch (IOException e) { e.printStackTrace(); } return builder.toString(); } public static int loadShader(int type, String shaderCode) { int shader = glCreateShader(type); glShaderSource(shader, shaderCode); glCompileShader(shader); int[] compiled = new int[1]; glGetShaderiv(shader, GL_COMPILE_STATUS, compiled, 0); if (compiled[0] == 0) { Log.e(TAG, glGetShaderInfoLog(shader)); glDeleteShader(shader); return 0; } return shader; }triangle_v.glsl代码如下:
#version 300 es uniform mat4 uMVPMatrix; layout (location = 0) in vec4 aPosition; layout (location = 1) in vec4 aColor; out vec4 vColor; void main() { gl_Position = uMVPMatrix * aPosition; vColor = aColor; }triangle_f.glsl代码如下:
#version 300 es precision mediump float; in vec4 vColor; out vec4 fragColor; void main() { fragColor = vColor; }然后在onSurfaceChanged里执行如下代码:
float ratio = (float) height / width; Matrix.frustumM(frustumM, 0, -1, 1, -ratio, ratio, 3, 7); Matrix.setLookAtM(lookAtM, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0); Matrix.multiplyMM(mMVPMatrix, 0, frustumM, 0, lookAtM, 0);最后在onDrawFrame里执行:
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT); GLES30.glUseProgram(mProgram); GLES30.glUniformMatrix4fv(muMVPMatrixHandler, 1, false, mMVPMatrix, 0); GLES30.glVertexAttribPointer(mPosHandler, 3, GLES30.GL_FLOAT, false, 3 * 4, mVertexBuffer); GLES30.glEnableVertexAttribArray(mPosHandler); GLES30.glVertexAttribPointer(mColorHandler, 4, GLES30.GL_FLOAT, false, 4 * 4, mColorBuffer); GLES30.glEnableVertexAttribArray(mColorHandler); GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3);至此就可以绘制出上面截图中的三角形了。