------------------ VERTEX shader ------------------
 
#version 420
 
in  vec4 vVertex;                 // Incoming vertex attribute
in  vec3 vNormal;                 // Incoming normal attribute
 
smooth out vec3 vVaryingNormal;   // NEW: Outgoing interpolated normal
smooth out vec3 vVaryingLightDir; // NEW: Outgoing interpolated direction to light source
 
uniform mat4 pMatrix;             // Projection matrix
uniform mat4 vMatrix;             // View matrix
uniform mat4 mMatrix;             // Model matrix
uniform mat3 normalMatrix;        // Normal matrix (3x3)
 
void main(void)
{
        // Specify light position
        vec3 vLightPosition = vec3(0.0, 0.0, 10.0);
 
        // Get vertex normal in eye coodinates and output to fragment shader for interpolation
        vVaryingNormal = normalMatrix * vNormal;
 
        // Create the ModelView matrix
        mat4 mvMatrix = vMatrix * mMatrix;
       
        // Get vertex position in eye coordinates and normalize it by dividing by w
        vec4 vPosition4 = mvMatrix * vVertex;
        vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
 
        // Get vector to light source to output to fragment shader for interpolation
        vVaryingLightDir = normalize(vLightPosition - vPosition3);
   
        // Calculate the final vertex screen position
        gl_Position = pMatrix * mvMatrix * vVertex;
}
 
----------------- FRAGMENT shader ---------------------------
 
#version 420
 
// Input from our vertex shader
in vec3 vVaryingNormal;
in vec3 vVaryingLightDir;
 
// Output fragments
out vec4 vFragColour;
 
void main(void)
{
    vec4 ambientColour  = vec4(0.2, 0.2, 0.2, 1.0);
    vec4 diffuseColour  = vec4(0.6, 0.6, 0.6, 1.0);
    vec4 specularColour = vec4(1.0, 1.0, 1.0, 1.0);
 
    // Start by adding in ambient colour
    vFragColour = ambientColour;
 
    // Calculate the diffuse intensity by getting the dot product of the normal and the light direction
    float diffuseIntensity = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));
 
    // Add in diffuse colour calculated as multiplication of diffuse intensity and diffuse colour
    vFragColour += diffuseIntensity * diffuseColour;
 
    // Specular light
    vec3 vReflectionVector  = normalize(reflect(normalize(-vVaryingNormal), normalize(vVaryingLightDir)));
    float specularIntensity = max(0.0, dot(normalize(vVaryingNormal), vReflectionVector));
   
    // If the diffuse light is more than zero then (and only then) calculate specular contribution (pow function is expensive!)
    if (diffuseIntensity > 0.0)
    {
        float fSpec = pow(specularIntensity, 32.0);
        vFragColour.rgb += vec3(fSpec * specularColour.rgb);
    }
}