------------------ 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); } }