text: // The MIT License (MIT)
  //
  // Copyright (c) 2013 Dan Ginsburg, Budirijanto Purnomo
  //
  // Permission is hereby granted, free of charge, to any person obtaining a copy
  // of this software and associated documentation files (the "Software"), to deal
  // in the Software without restriction, including without limitation the rights
  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  // copies of the Software, and to permit persons to whom the Software is
  // furnished to do so, subject to the following conditions:
  //
  // The above copyright notice and this permission notice shall be included in
  // all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  // THE SOFTWARE.
  
  //
  // Book:      OpenGL(R) ES 3.0 Programming Guide, 2nd Edition
  // Authors:   Dan Ginsburg, Budirijanto Purnomo, Dave Shreiner, Aaftab Munshi
  // ISBN-10:   0-321-93388-5
  // ISBN-13:   978-0-321-93388-1
  // Publisher: Addison-Wesley Professional
  // URLs:      http://www.opengles-book.com
  //            http://my.safaribooksonline.com/book/animation-and-3d/9780133440133
  //
  // ESShader.c
  //
  //    Utility functions for loading shaders and creating program objects.
  //
  
  ///
  //  Includes
  //
  #include "esUtil.h"
  #include <stdlib.h>
  
  //////////////////////////////////////////////////////////////////
  //
  //  Private Functions
  //
  //
  
  
  
  //////////////////////////////////////////////////////////////////
  //
  //  Public Functions
  //
  //
  
  //
  ///
  /// \brief Load a shader, check for compile errors, print error messages to output log
  /// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
  /// \param shaderSrc Shader source string
  /// \return A new shader object on success, 0 on failure
  //
  GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc )
  {
     GLuint shader;
     GLint compiled;
  
     // Create the shader object
     shader = glCreateShader ( type );
  
     if ( shader == 0 )
     {
        return 0;
     }
  
     // Load the shader source
     glShaderSource ( shader, 1, &shaderSrc, NULL );
  
     // Compile the shader
     glCompileShader ( shader );
  
     // Check the compile status
     glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
  
     if ( !compiled )
     {
        GLint infoLen = 0;
  
        glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
  
        if ( infoLen > 1 )
        {
           char *infoLog = malloc ( sizeof ( char ) * infoLen );
  
           glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
           esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
  
           free ( infoLog );
        }
  
        glDeleteShader ( shader );
        return 0;
     }
  
     return shader;
  
  }
  
  
  //
  ///
  /// \brief Load a vertex and fragment shader, create a program object, link program.
  //         Errors output to log.
  /// \param vertShaderSrc Vertex shader source code
  /// \param fragShaderSrc Fragment shader source code
  /// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
  //
  GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc )
  {
     GLuint vertexShader;
     GLuint fragmentShader;
     GLuint programObject;
     GLint linked;
  
     // Load the vertex/fragment shaders
     vertexShader = esLoadShader ( GL_VERTEX_SHADER, vertShaderSrc );
  
     if ( vertexShader == 0 )
     {
        return 0;
     }
  
     fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
  
     if ( fragmentShader == 0 )
     {
        glDeleteShader ( vertexShader );
        return 0;
     }
  
     // Create the program object
     programObject = glCreateProgram ( );
  
     if ( programObject == 0 )
     {
        return 0;
     }
  
     glAttachShader ( programObject, vertexShader );
     glAttachShader ( programObject, fragmentShader );
  
     // Link the program
     glLinkProgram ( programObject );
  
     // Check the link status
     glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
  
     if ( !linked )
     {
        GLint infoLen = 0;
  
        glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
  
        if ( infoLen > 1 )
        {
           char *infoLog = malloc ( sizeof ( char ) * infoLen );
  
           glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
           esLogMessage ( "Error linking program:\n%s\n", infoLog );
  
           free ( infoLog );
        }
  
        glDeleteProgram ( programObject );
        return 0;
     }
  
     // Free up no longer needed shader resources
     glDeleteShader ( vertexShader );
     glDeleteShader ( fragmentShader );
  
     return programObject;
  }