// Path: gltoolkit/src/main/java/com/quan404/gltoolkit/ShaderHelper.java
// public class ShaderHelper {
//     private static final String TAG = "ShaderHelper";
// 
//     public static int compileVertexShader(String code){
//         return compileShader(GLES20.GL_VERTEX_SHADER, code);
//     }
// 
//     public static int compileFragmentShader(String code){
//         return compileShader(GLES20.GL_FRAGMENT_SHADER, code);
//     }
// 
//     private static int compileShader(int type, String code){
//         final int shaderObjectId = GLES20.glCreateShader(type);
// 
//         if (shaderObjectId == 0){
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Could not create new shader");
//             }
//             return 0;
//         }
// 
//         GLES20.glShaderSource(shaderObjectId, code);
//         GLES20.glCompileShader(shaderObjectId);
// 
//         final int[] compileStatus = new int[1];
//         GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// 
//         if (LoggerConfig.ON){
//             Log.v(TAG, "Results of compiling source: " + "\n" + code + "\n" + GLES20.glGetShaderInfoLog(shaderObjectId));
//         }
// 
//         if (compileStatus[0] == 0){
//             // if it failed, delete the shader object
//             GLES20.glDeleteShader(shaderObjectId);
// 
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Compilation of shader failed");
//             }
//             return 0;
//         }
//         return shaderObjectId;
//     }
// 
//     public static int linkProgram(int vertexShaderId, int fragmentShaderId){
//         final int programObjectId = GLES20.glCreateProgram();
// 
//         if(programObjectId == 0){
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Could not create new program");
//             }
//             return 0;
//         }
// 
//         GLES20.glAttachShader(programObjectId, vertexShaderId);
//         GLES20.glAttachShader(programObjectId, fragmentShaderId);
// 
//         GLES20.glLinkProgram(programObjectId);
// 
//         final int[] linkStatus = new int[1];
//         GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0);
//         if (LoggerConfig.ON){
//             Log.v(TAG, "Results of linking program: " + "\n" + GLES20.glGetProgramInfoLog(programObjectId));
//         }
// 
//         if (linkStatus[0] == 0){
//             // if it failed, delete the shader object
//             GLES20.glDeleteProgram(programObjectId);
// 
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Linking of program failed");
//             }
//             return 0;
//         }
//         return programObjectId;
//     }
// 
//     public static boolean validateProgram(int programObjectId) {
//         GLES20.glValidateProgram(programObjectId);
// 
//         final int[] validateStatus = new int[1];
//         GLES20.glGetProgramiv(programObjectId, GLES20.GL_VALIDATE_STATUS, validateStatus, 0);
//         if (LoggerConfig.ON){
//             Log.v(TAG, "Results of validating program: " + validateStatus[0] + "\nLog: " + GLES20.glGetProgramInfoLog(programObjectId));
//         }
//         return validateStatus[0] != 0;
//     }
// 
//     public static int buildProgram(String vertexShaderSource, String fragmentShaderSource){
//         int program;
// 
//         // compile the shaders
//         int vertexShader = compileVertexShader(vertexShaderSource);
//         int fragmentShader = compileFragmentShader(fragmentShaderSource);
// 
//         // link them into a shader program
//         program = linkProgram(vertexShader, fragmentShader);
// 
//         if (LoggerConfig.ON){
//             validateProgram(program);
//         }
// 
//         return program;
//     }
// }
// 
// Path: gltoolkit/src/main/java/com/quan404/gltoolkit/TextResourceReader.java
// public class TextResourceReader {
//     public static String readTextFileFromResource(Context context, int resourceId) {
//         StringBuilder body = new StringBuilder();
// 
//         try{
//             InputStream inputStream = context.getResources().openRawResource(resourceId);
//             InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
// 
//             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 
//             String nextLine;
// 
//             while ((nextLine = bufferedReader.readLine()) != null){
//                 body.append(nextLine);
//                 body.append("\n");
//             }
//         }catch (IOException e){
//             throw new RuntimeException("Could not open resource: " + resourceId, e);
//         } catch (Resources.NotFoundException nfe){
//             throw new RuntimeException("Resource not found: " + resourceId, nfe);
//         }
// 
//         return body.toString();
//     }
// }


import android.content.Context;
import android.opengl.GLES20;
import android.util.Log;
import com.quan404.gltoolkit.ShaderHelper;
import com.quan404.gltoolkit.TextResourceReader;
package com.quan404.gltoolkit.programs;



/**
 * Created by quanhua on 05/01/2016.
 */
abstract class ShaderProgram {
    // Uniform constants
    protected static final String U_MATRIX = "u_Matrix";
    protected static final String U_TEXTURE_UNIT = "u_TextureUnit";
    protected static final String U_COLOR = "u_Color";
    protected static final String U_MVPMATRIX = "u_MVPMatrix";
    protected static final String U_STMATRIX = "u_STMatrix";

    // Attribute constants
    protected static final String A_POSITION = "a_Position";
    protected static final String A_COLOR = "a_Color";
    protected static final String A_TEXTURE_COORDINATES = "a_TextureCoordinates";

    // Shader program
    protected final int program;
    protected ShaderProgram(Context context, int vertexShaderResourceId, int fragmentShaderResourceId) {
        program = ShaderHelper.buildProgram(
                TextResourceReader.readTextFileFromResource(context, vertexShaderResourceId),
// Path: gltoolkit/src/main/java/com/quan404/gltoolkit/ShaderHelper.java
// public class ShaderHelper {
//     private static final String TAG = "ShaderHelper";
// 
//     public static int compileVertexShader(String code){
//         return compileShader(GLES20.GL_VERTEX_SHADER, code);
//     }
// 
//     public static int compileFragmentShader(String code){
//         return compileShader(GLES20.GL_FRAGMENT_SHADER, code);
//     }
// 
//     private static int compileShader(int type, String code){
//         final int shaderObjectId = GLES20.glCreateShader(type);
// 
//         if (shaderObjectId == 0){
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Could not create new shader");
//             }
//             return 0;
//         }
// 
//         GLES20.glShaderSource(shaderObjectId, code);
//         GLES20.glCompileShader(shaderObjectId);
// 
//         final int[] compileStatus = new int[1];
//         GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// 
//         if (LoggerConfig.ON){
//             Log.v(TAG, "Results of compiling source: " + "\n" + code + "\n" + GLES20.glGetShaderInfoLog(shaderObjectId));
//         }
// 
//         if (compileStatus[0] == 0){
//             // if it failed, delete the shader object
//             GLES20.glDeleteShader(shaderObjectId);
// 
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Compilation of shader failed");
//             }
//             return 0;
//         }
//         return shaderObjectId;
//     }
// 
//     public static int linkProgram(int vertexShaderId, int fragmentShaderId){
//         final int programObjectId = GLES20.glCreateProgram();
// 
//         if(programObjectId == 0){
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Could not create new program");
//             }
//             return 0;
//         }
// 
//         GLES20.glAttachShader(programObjectId, vertexShaderId);
//         GLES20.glAttachShader(programObjectId, fragmentShaderId);
// 
//         GLES20.glLinkProgram(programObjectId);
// 
//         final int[] linkStatus = new int[1];
//         GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0);
//         if (LoggerConfig.ON){
//             Log.v(TAG, "Results of linking program: " + "\n" + GLES20.glGetProgramInfoLog(programObjectId));
//         }
// 
//         if (linkStatus[0] == 0){
//             // if it failed, delete the shader object
//             GLES20.glDeleteProgram(programObjectId);
// 
//             if (LoggerConfig.ON){
//                 Log.w(TAG, "Linking of program failed");
//             }
//             return 0;
//         }
//         return programObjectId;
//     }
// 
//     public static boolean validateProgram(int programObjectId) {
//         GLES20.glValidateProgram(programObjectId);
// 
//         final int[] validateStatus = new int[1];
//         GLES20.glGetProgramiv(programObjectId, GLES20.GL_VALIDATE_STATUS, validateStatus, 0);
//         if (LoggerConfig.ON){
//             Log.v(TAG, "Results of validating program: " + validateStatus[0] + "\nLog: " + GLES20.glGetProgramInfoLog(programObjectId));
//         }
//         return validateStatus[0] != 0;
//     }
// 
//     public static int buildProgram(String vertexShaderSource, String fragmentShaderSource){
//         int program;
// 
//         // compile the shaders
//         int vertexShader = compileVertexShader(vertexShaderSource);
//         int fragmentShader = compileFragmentShader(fragmentShaderSource);
// 
//         // link them into a shader program
//         program = linkProgram(vertexShader, fragmentShader);
// 
//         if (LoggerConfig.ON){
//             validateProgram(program);
//         }
// 
//         return program;
//     }
// }
// 
// Path: gltoolkit/src/main/java/com/quan404/gltoolkit/TextResourceReader.java
// public class TextResourceReader {
//     public static String readTextFileFromResource(Context context, int resourceId) {
//         StringBuilder body = new StringBuilder();
// 
//         try{
//             InputStream inputStream = context.getResources().openRawResource(resourceId);
//             InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
// 
//             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 
//             String nextLine;
// 
//             while ((nextLine = bufferedReader.readLine()) != null){
//                 body.append(nextLine);
//                 body.append("\n");
//             }
//         }catch (IOException e){
//             throw new RuntimeException("Could not open resource: " + resourceId, e);
//         } catch (Resources.NotFoundException nfe){
//             throw new RuntimeException("Resource not found: " + resourceId, nfe);
//         }
// 
//         return body.toString();
//     }
// }


// Path: gltoolkit/src/main/java/com/quan404/gltoolkit/programs/ShaderProgram.java
import android.content.Context;
import android.opengl.GLES20;
import android.util.Log;
import com.quan404.gltoolkit.ShaderHelper;
import com.quan404.gltoolkit.TextResourceReader;

package com.quan404.gltoolkit.programs;



/**
 * Created by quanhua on 05/01/2016.
 */
abstract class ShaderProgram {
    // Uniform constants
    protected static final String U_MATRIX = "u_Matrix";
    protected static final String U_TEXTURE_UNIT = "u_TextureUnit";
    protected static final String U_COLOR = "u_Color";
    protected static final String U_MVPMATRIX = "u_MVPMatrix";
    protected static final String U_STMATRIX = "u_STMatrix";

    // Attribute constants
    protected static final String A_POSITION = "a_Position";
    protected static final String A_COLOR = "a_Color";
    protected static final String A_TEXTURE_COORDINATES = "a_TextureCoordinates";

    // Shader program
    protected final int program;
    protected ShaderProgram(Context context, int vertexShaderResourceId, int fragmentShaderResourceId) {
        program = ShaderHelper.buildProgram(
                TextResourceReader.readTextFileFromResource(context, vertexShaderResourceId),
                TextResourceReader.readTextFileFromResource(context, fragmentShaderResourceId));