public void onDrawFrame(GL10 glUnused)
            {
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

                // Do a complete rotation every 10 seconds.
                long  time           = SystemClock.uptimeMillis() % 10000L;
                float angleInDegrees = (360.0f / 10000.0f) * ((int)time);

                // Set our per-vertex lighting program.
                gl.useProgram(mProgramHandle);

                // Set program handles for cube drawing.
                mMVPMatrixHandle      = gl.getUniformLocation(mProgramHandle, "u_MVPMatrix");
                mMVMatrixHandle       = gl.getUniformLocation(mProgramHandle, "u_MVMatrix");
                mLightPosHandle       = gl.getUniformLocation(mProgramHandle, "u_LightPos");
                mTextureUniformHandle = gl.getUniformLocation(mProgramHandle, "u_Texture");

                mPositionHandle          = gl.getAttribLocation(mProgramHandle, "a_Position");
                mColorHandle             = gl.getAttribLocation(mProgramHandle, "a_Color");
                mNormalHandle            = gl.getAttribLocation(mProgramHandle, "a_Normal");
                mTextureCoordinateHandle = gl.getAttribLocation(mProgramHandle, "a_TexCoordinate");

                // Set the active texture unit to texture unit 0.
                gl.activeTexture(gl.TEXTURE0);

                // Bind the texture to this unit.
                gl.bindTexture(gl.TEXTURE_2D, mTextureDataHandle);

                // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
                gl.uniform1i(mTextureUniformHandle, 0);

                // Calculate position of the light. Rotate and then push into the distance.
                Matrix.setIdentityM(mLightModelMatrix, 0);
                Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, -5.0f);
                Matrix.rotateM(mLightModelMatrix, 0, angleInDegrees, 0.0f, 1.0f, 0.0f);
                Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, 2.0f);

                Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0);
                Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0);

                #region drawCube
                Action drawCube =
                    delegate
                {
                    // Pass in the position information
                    mCubePositions.position(0);
                    opengl.glVertexAttribPointer(mPositionHandle, mPositionDataSize, (int)gl.FLOAT, false,
                                                 0, mCubePositions);

                    gl.enableVertexAttribArray((uint)mPositionHandle);

                    // Pass in the color information
                    mCubeColors.position(0);
                    opengl.glVertexAttribPointer(mColorHandle, mColorDataSize, (int)gl.FLOAT, false,
                                                 0, mCubeColors);

                    gl.enableVertexAttribArray((uint)mColorHandle);

                    // Pass in the normal information
                    mCubeNormals.position(0);
                    opengl.glVertexAttribPointer(mNormalHandle, mNormalDataSize, (int)gl.FLOAT, false,
                                                 0, mCubeNormals);

                    gl.enableVertexAttribArray((uint)mNormalHandle);

                    // Pass in the texture coordinate information
                    mCubeTextureCoordinates.position(0);
                    opengl.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, opengl.GL_FLOAT, false,
                                                 0, mCubeTextureCoordinates);

                    gl.enableVertexAttribArray((uint)mTextureCoordinateHandle);

                    // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
                    // (which currently contains model * view).
                    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

                    // Pass in the modelview matrix.
                    gl.uniformMatrix4fv(mMVMatrixHandle, false, mMVPMatrix);

                    // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
                    // (which now contains model * view * projection).
                    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

                    // Pass in the combined matrix.
                    gl.uniformMatrix4fv(mMVPMatrixHandle, false, mMVPMatrix);

                    // Pass in the light position in eye space.
                    gl.uniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);

                    // Draw the cube.
                    gl.drawArrays(gl.TRIANGLES, 0, 36);
                };
                #endregion

                // Draw some cubes.
                Matrix.setIdentityM(mModelMatrix, 0);
                Matrix.translateM(mModelMatrix, 0, 4.0f, 0.0f, -7.0f);
                Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 0.0f, 0.0f);
                drawCube();

                Matrix.setIdentityM(mModelMatrix, 0);
                Matrix.translateM(mModelMatrix, 0, -4.0f, 0.0f, -7.0f);
                Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 1.0f, 0.0f);
                drawCube();

                Matrix.setIdentityM(mModelMatrix, 0);
                Matrix.translateM(mModelMatrix, 0, 0.0f, 4.0f, -7.0f);
                Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);
                drawCube();

                Matrix.setIdentityM(mModelMatrix, 0);
                Matrix.translateM(mModelMatrix, 0, 0.0f, -4.0f, -7.0f);
                drawCube();

                Matrix.setIdentityM(mModelMatrix, 0);
                Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
                Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f);
                drawCube();

                #region drawLight
                Action drawLight =
                    delegate
                {
                    var pointMVPMatrixHandle = gl.getUniformLocation(mPointProgramHandle, "u_MVPMatrix");
                    var pointPositionHandle  = gl.getAttribLocation(mPointProgramHandle, "a_Position");

                    // Pass in the position.
                    gl.vertexAttrib3f((uint)pointPositionHandle, mLightPosInModelSpace[0], mLightPosInModelSpace[1], mLightPosInModelSpace[2]);

                    // Since we are not using a buffer object, disable vertex arrays for this attribute.
                    gl.disableVertexAttribArray((uint)pointPositionHandle);

                    // Pass in the transformation matrix.
                    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mLightModelMatrix, 0);
                    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
                    gl.uniformMatrix4fv(pointMVPMatrixHandle, false, mMVPMatrix);

                    // Draw the point.
                    gl.drawArrays(gl.POINTS, 0, 1);
                };
                #endregion

                // Draw a point to indicate the light.
                gl.useProgram(mPointProgramHandle);
                drawLight();
            }