* mColorHandle = GLES20.glGetUniformLocation(mProgram, "uColor"); * MyGLRenderer.checkGlError("glGetUniformLocation");
Note This is quite slow so it's best to use it sparingly in production builds. * * @param glOperation name of the OpenGL call to check */ private static void checkGlError(String glOperation) { int error = GLES20.glGetError(); if (error != GLES20.GL_NO_ERROR) { String errorString = GLU.gluErrorString(error); if (errorString == null) { errorString = GLUtils.getEGLErrorString(error); } String message = glOperation + " caused GL error 0x" + Integer.toHexString(error) + ": " + errorString; Log.e(TAG, message); throw new RuntimeException(message); } } /** * Compiles an OpenGL shader. * * @param type {@link GLES20#GL_VERTEX_SHADER} or {@link GLES20#GL_FRAGMENT_SHADER} * @param shaderCode string containing the shader source code * @return ID for the shader */ private static int loadShader(int type, String shaderCode){ // Create a vertex or fragment shader. int shader = GLES20.glCreateShader(type); if (CHECK_GL_ERRORS) checkGlError("glCreateShader"); if (shader == 0) { throw new IllegalStateException("glCreateShader failed"); } // Add the source code to the shader and compile it. GLES20.glShaderSource(shader, shaderCode); if (CHECK_GL_ERRORS) checkGlError("glShaderSource"); GLES20.glCompileShader(shader); if (CHECK_GL_ERRORS) checkGlError("glCompileShader"); return shader; } /** OpenGL shaders for drawing solid colored triangle lists. */ public static class Program { /** Trivial vertex shader that transforms the input vertex by the MVP matrix. */ private static final String VERTEX_SHADER_CODE = "" + "uniform mat4 uMvpMatrix;\n" + "attribute vec4 aPosition;\n" + "void main() {\n" + " gl_Position = uMvpMatrix * aPosition;\n" + "}\n"; /** Trivial fragment shader that draws with a fixed color. */ private static final String FRAGMENT_SHADER_CODE = "" + "precision mediump float;\n" + "uniform vec4 uColor;\n" + "void main() {\n" + " gl_FragColor = uColor;\n" + "}\n"; /** ID OpenGL uses to identify this program. */ private final int mProgramId; /** Handle for uMvpMatrix uniform in vertex shader. */ private final int mMvpMatrixHandle; /** Handle for aPosition attribute in vertex shader. */ private final int mPositionHandle; /** Handle for uColor uniform in fragment shader. */ private final int mColorHandle; /** * Creates a program to draw triangle lists. For optimal drawing efficiency, one program * should be used for all triangle lists being drawn. */ public Program() { // Prepare shaders. int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE); int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE); // Create empty OpenGL Program. mProgramId = GLES20.glCreateProgram(); if (CHECK_GL_ERRORS) checkGlError("glCreateProgram"); if (mProgramId == 0) { throw new IllegalStateException("glCreateProgram failed"); } // Add the shaders to the program. GLES20.glAttachShader(mProgramId, vertexShader); if (CHECK_GL_ERRORS) checkGlError("glAttachShader"); GLES20.glAttachShader(mProgramId, fragmentShader); if (CHECK_GL_ERRORS) checkGlError("glAttachShader"); // Link the program so it can be executed. GLES20.glLinkProgram(mProgramId); if (CHECK_GL_ERRORS) checkGlError("glLinkProgram"); // Get a handle to the uMvpMatrix uniform in the vertex shader. mMvpMatrixHandle = GLES20.glGetUniformLocation(mProgramId, "uMvpMatrix"); if (CHECK_GL_ERRORS) checkGlError("glGetUniformLocation"); // Get a handle to the vertex shader's aPosition attribute. mPositionHandle = GLES20.glGetAttribLocation(mProgramId, "aPosition"); if (CHECK_GL_ERRORS) checkGlError("glGetAttribLocation"); // Enable vertex array (VBO). GLES20.glEnableVertexAttribArray(mPositionHandle); if (CHECK_GL_ERRORS) checkGlError("glEnableVertexAttribArray"); // Get a handle to fragment shader's uColor uniform. mColorHandle = GLES20.glGetUniformLocation(mProgramId, "uColor"); if (CHECK_GL_ERRORS) checkGlError("glGetUniformLocation"); } /** * Tells OpenGL to use this program. Call this method before drawing a sequence of * triangle lists. */ public void use() { GLES20.glUseProgram(mProgramId); if (CHECK_GL_ERRORS) checkGlError("glUseProgram"); } /** Sends the given MVP matrix, vertex data, and color to OpenGL. */ public void bind(float[] mvpMatrix, FloatBuffer vertexBuffer, float[] color) { // Pass the MVP matrix to OpenGL. GLES20.glUniformMatrix4fv(mMvpMatrixHandle, 1 /* count */, false /* transpose */, mvpMatrix, 0 /* offset */); if (CHECK_GL_ERRORS) checkGlError("glUniformMatrix4fv"); // Pass the VBO with the triangle list's vertices to OpenGL. GLES20.glEnableVertexAttribArray(mPositionHandle); if (CHECK_GL_ERRORS) checkGlError("glEnableVertexAttribArray"); GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false /* normalized */, VERTEX_STRIDE, vertexBuffer); if (CHECK_GL_ERRORS) checkGlError("glVertexAttribPointer"); // Pass the triangle list's color to OpenGL. GLES20.glUniform4fv(mColorHandle, 1 /* count */, color, 0 /* offset */); if (CHECK_GL_ERRORS) checkGlError("glUniform4fv"); } } }