  // Source code of fragment shader
   precision mediump float;
   varying vec3 N;
   varying vec3 L;
   varying vec3 V; 
   uniform vec4 lightAmbient;
   uniform vec4 lightDiffuse;
   uniform vec4 lightSpecular;
   //in this example, material color same for ambient, diffuse, specular
   uniform vec4 materialColor;
   uniform float shininess;

   void main() {
     vec3 norm = normalize(N);
     vec3 lightv = normalize(L);
     vec3 viewv = normalize(V);
     // diffuse coefficient
     float Kd = max(0.0, dot(lightv, norm));

     // calculating specular coefficient
     // consider only specular light in same direction as normal
     float cs;
     if(dot(lightv, norm)>= 0.0) cs =1.0;
     else cs = 0.0;
     //reflection vector
     vec3 r = 2.0 *  dot (norm, lightv) * norm  - lightv;
     float Ks = pow(max(0.0, dot(r, viewv)), shininess);
     
     vec4 ambient = materialColor * lightAmbient;
     vec4 specular = cs * Ks * materialColor *lightSpecular;
     vec4 diffuse = Kd * materialColor *  lightDiffuse;  
    
     gl_FragColor = ambient + diffuse + specular;
   }
