12f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich/*
22f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * Copyright (C) 2011 The Android Open Source Project
32f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich *
42f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * Licensed under the Apache License, Version 2.0 (the "License");
52f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * you may not use this file except in compliance with the License.
62f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * You may obtain a copy of the License at
72f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich *
82f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich *      http://www.apache.org/licenses/LICENSE-2.0
92f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich *
102f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * Unless required by applicable law or agreed to in writing, software
112f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * distributed under the License is distributed on an "AS IS" BASIS,
122f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * See the License for the specific language governing permissions and
142f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich * limitations under the License.
152f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich */
162f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
172f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichpackage com.example.android.basicglsurfaceview;
182f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
192f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport java.io.IOException;
202f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport java.io.InputStream;
212f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport java.nio.ByteBuffer;
222f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport java.nio.ByteOrder;
232f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport java.nio.FloatBuffer;
242f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
252f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport javax.microedition.khronos.egl.EGLConfig;
262f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport javax.microedition.khronos.opengles.GL10;
272f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
282f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.content.Context;
292f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.graphics.Bitmap;
302f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.graphics.BitmapFactory;
312f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.opengl.GLES20;
322f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.opengl.GLSurfaceView;
332f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.opengl.GLUtils;
342f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.opengl.Matrix;
352f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.os.SystemClock;
362f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichimport android.util.Log;
372f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
382f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevichclass GLES20TriangleRenderer implements GLSurfaceView.Renderer {
392f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
402f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    public GLES20TriangleRenderer(Context context) {
412f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        mContext = context;
422f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
432f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
442f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        mTriangleVertices.put(mTriangleVerticesData).position(0);
452f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    }
462f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
472f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    public void onDrawFrame(GL10 glUnused) {
482f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        // Ignore the passed-in GL10 interface, and use the GLES20
492f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        // class's static methods instead.
502f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
512f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
522f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glUseProgram(mProgram);
532f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glUseProgram");
542f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
552f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
562f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
572f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
582f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
592f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
602f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
612f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glVertexAttribPointer maPosition");
622f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
632f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glEnableVertexAttribArray(maPositionHandle);
642f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glEnableVertexAttribArray maPositionHandle");
652f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
662f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
672f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glVertexAttribPointer maTextureHandle");
682f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glEnableVertexAttribArray(maTextureHandle);
692f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glEnableVertexAttribArray maTextureHandle");
702f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
712f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        long time = SystemClock.uptimeMillis() % 4000L;
722f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        float angle = 0.090f * ((int) time);
732f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f);
742f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
752f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
762f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
772f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
782f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
792f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glDrawArrays");
802f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    }
812f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
822f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
832f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        // Ignore the passed-in GL10 interface, and use the GLES20
842f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        // class's static methods instead.
852f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glViewport(0, 0, width, height);
862f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        float ratio = (float) width / height;
872f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
882f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    }
892f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
902f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
912f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        // Ignore the passed-in GL10 interface, and use the GLES20
922f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        // class's static methods instead.
932f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        mProgram = createProgram(mVertexShader, mFragmentShader);
942f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (mProgram == 0) {
952f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            return;
962f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
972f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
982f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glGetAttribLocation aPosition");
992f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (maPositionHandle == -1) {
1002f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            throw new RuntimeException("Could not get attrib location for aPosition");
1012f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1022f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
1032f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glGetAttribLocation aTextureCoord");
1042f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (maTextureHandle == -1) {
1052f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            throw new RuntimeException("Could not get attrib location for aTextureCoord");
1062f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1072f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1082f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
1092f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        checkGlError("glGetUniformLocation uMVPMatrix");
1102f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (muMVPMatrixHandle == -1) {
1112f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            throw new RuntimeException("Could not get attrib location for uMVPMatrix");
1122f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1132f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1142f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        /*
1152f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich         * Create our texture. This has to be done each time the
1162f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich         * surface is created.
1172f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich         */
1182f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1192f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        int[] textures = new int[1];
1202f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glGenTextures(1, textures, 0);
1212f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1222f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        mTextureID = textures[0];
1232f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
1242f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1252f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
1262f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                GLES20.GL_NEAREST);
1272f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
1282f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                GLES20.GL_TEXTURE_MAG_FILTER,
1292f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                GLES20.GL_LINEAR);
1302f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1312f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
1322f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                GLES20.GL_REPEAT);
1332f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
1342f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                GLES20.GL_REPEAT);
1352f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1362f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        InputStream is = mContext.getResources()
1372f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            .openRawResource(R.raw.robot);
1382f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        Bitmap bitmap;
1392f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        try {
1402f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            bitmap = BitmapFactory.decodeStream(is);
1412f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        } finally {
1422f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            try {
1432f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                is.close();
1442f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            } catch(IOException e) {
1452f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                // Ignore.
1462f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            }
1472f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1482f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1492f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
1502f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        bitmap.recycle();
1512f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1522f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
1532f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    }
1542f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1552f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private int loadShader(int shaderType, String source) {
1562f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        int shader = GLES20.glCreateShader(shaderType);
1572f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (shader != 0) {
1582f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            GLES20.glShaderSource(shader, source);
1592f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            GLES20.glCompileShader(shader);
1602f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            int[] compiled = new int[1];
1612f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
1622f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            if (compiled[0] == 0) {
1632f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                Log.e(TAG, "Could not compile shader " + shaderType + ":");
1642f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
1652f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                GLES20.glDeleteShader(shader);
1662f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                shader = 0;
1672f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            }
1682f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1692f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        return shader;
1702f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    }
1712f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1722f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private int createProgram(String vertexSource, String fragmentSource) {
1732f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
1742f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (vertexShader == 0) {
1752f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            return 0;
1762f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1772f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1782f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
1792f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (pixelShader == 0) {
1802f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            return 0;
1812f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1822f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
1832f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        int program = GLES20.glCreateProgram();
1842f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        if (program != 0) {
1852f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            GLES20.glAttachShader(program, vertexShader);
1862f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            checkGlError("glAttachShader");
1872f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            GLES20.glAttachShader(program, pixelShader);
1882f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            checkGlError("glAttachShader");
1892f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            GLES20.glLinkProgram(program);
1902f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            int[] linkStatus = new int[1];
1912f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
1922f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            if (linkStatus[0] != GLES20.GL_TRUE) {
1932f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                Log.e(TAG, "Could not link program: ");
1942f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                Log.e(TAG, GLES20.glGetProgramInfoLog(program));
1952f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                GLES20.glDeleteProgram(program);
1962f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich                program = 0;
1972f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            }
1982f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
1992f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        return program;
2002f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    }
2012f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2022f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private void checkGlError(String op) {
2032f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        int error;
2042f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
2052f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            Log.e(TAG, op + ": glError " + error);
2062f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            throw new RuntimeException(op + ": glError " + error);
2072f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        }
2082f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    }
2092f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2102f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private static final int FLOAT_SIZE_BYTES = 4;
2112f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
2122f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
2132f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
2142f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private final float[] mTriangleVerticesData = {
2152f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            // X, Y, Z, U, V
2162f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            -1.0f, -0.5f, 0, -0.5f, 0.0f,
2172f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            1.0f, -0.5f, 0, 1.5f, -0.0f,
2182f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich            0.0f,  1.11803399f, 0, 0.5f,  1.61803399f };
2192f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2202f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private FloatBuffer mTriangleVertices;
2212f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2222f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private final String mVertexShader =
2232f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "uniform mat4 uMVPMatrix;\n" +
2242f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "attribute vec4 aPosition;\n" +
2252f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "attribute vec2 aTextureCoord;\n" +
2262f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "varying vec2 vTextureCoord;\n" +
2272f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "void main() {\n" +
2282f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "  gl_Position = uMVPMatrix * aPosition;\n" +
2292f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "  vTextureCoord = aTextureCoord;\n" +
2302f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "}\n";
2312f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2322f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private final String mFragmentShader =
2332f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "precision mediump float;\n" +
2342f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "varying vec2 vTextureCoord;\n" +
2352f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "uniform sampler2D sTexture;\n" +
2362f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "void main() {\n" +
2372f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
2382f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich        "}\n";
2392f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2402f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private float[] mMVPMatrix = new float[16];
2412f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private float[] mProjMatrix = new float[16];
2422f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private float[] mMMatrix = new float[16];
2432f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private float[] mVMatrix = new float[16];
2442f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2452f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private int mProgram;
2462f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private int mTextureID;
2472f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private int muMVPMatrixHandle;
2482f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private int maPositionHandle;
2492f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private int maTextureHandle;
2502f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich
2512f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private Context mContext;
2522f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich    private static String TAG = "GLES20TriangleRenderer";
2532f6e41d6646a3eea54c3cb890ce32b6360d3d913Jack Palevich}
254