     return vNormal;
 }
 
-vec3 lighting()
+vec3 diffuse_lighting(void)
 {
-    return vec3(0);
+    vec3 vColor = vec3(0);
+    bool bFirst = true;
+
+    for(int i=0; i<NUM_LIGHTS; ++i)
+    {
+        if(u_Lights[i].bActive == false) continue;
+
+        // only set initial color to (1,1,1) if at least one light is active
+        // otherwise, color remains at (0,0,0)
+        if(bFirst == true)
+        {
+            bFirst = false;
+            vColor = vec3(1);
+        }
+
+        int type = u_Lights[i].nType;
+        vColor *= u_LightTypes[type].vDiffuse;
+    }
+
+    return vColor;
 }
 
 void main(void)

    return vTexCoord + vCurrOffset;
}

vec3 normal_mapping(sampler2D sMap, vec2 vTexCoord)
{
    vec3 vNormal = texture(sMap, vTexCoord).rgb * 2.0 - 1.0;



out vec4 o_vColor;

vec2 parallax_occlusion_mapping(in sampler2D sMap, in vec2 vTexCoord,
                                in vec3 vEye, in vec3 vNormal,
                                in float fScale, in float fMaxSamples, in float fMinSamples)
{
    float fParallaxLimit = -length(vEye.xy) / vEye.z * fScale;

