In the tutorial on textured spheres, the texture color was used as output of the fragment shader. However, it is also possible to use the texture color as any of the parameters in lighting computations, in particular the material constant for diffuse reflection, which was introduced in the tutorial on diffuse reflection. It appears in the diffuse part of the Phong reflection model:

where this equation is used with different material constants for the three color components red, green, and blue. By using a texture to determine these material constants, they can vary over the surface.

In comparison to the per-vertex lighting in the tutorial on specular highlights, the vertex shader here computes two varying colors: diffuseColor is multiplied with the texture color in the fragment shader and specularColor is just the specular term, which shouldn't be multiplied with the texture color. This makes perfect sense but for historically reasons (i.e. older graphics hardware that was less capable) this is sometimes referred to as “separate specular color”.

attributevec3v_coord;attributevec3v_normal;uniformmat4m,v,p;uniformmat3m_3x3_inv_transp;uniformmat4v_inv;varyingvec3diffuseColor;// the diffuse Phong lighting computed in the vertex shadervaryingvec3specularColor;// the specular Phong lighting computed in the vertex shadervaryingvec4texCoords;// the texture coordinatesstructlightSource{vec4position;vec4diffuse;vec4specular;floatconstantAttenuation,linearAttenuation,quadraticAttenuation;floatspotCutoff,spotExponent;vec3spotDirection;};lightSourcelight0=lightSource(vec4(0.0,1.0,2.0,1.0),vec4(1.0,1.0,1.0,1.0),vec4(1.0,1.0,1.0,1.0),0.0,1.0,0.0,180.0,0.0,vec3(0.0,0.0,0.0));vec4scene_ambient=vec4(0.2,0.2,0.2,1.0);structmaterial{vec4ambient;vec4diffuse;vec4specular;floatshininess;};materialmymaterial=material(vec4(0.2,0.2,0.2,1.0),vec4(1.0,0.8,0.8,1.0),vec4(1.0,1.0,1.0,1.0),5.0);voidmain(void){vec4v_coord4=vec4(v_coord,1.0);mat4mvp=p*v*m;vec3normalDirection=normalize(m_3x3_inv_transp*v_normal);vec3viewDirection=normalize(vec3(v_inv*vec4(0.0,0.0,0.0,1.0)-m*v_coord4));vec3lightDirection;floatattenuation;if(light0.position.w==0.0)// directional light{attenuation=1.0;// no attenuationlightDirection=normalize(vec3(light0.position));}else// point or spot light (or other kind of light){vec3vertexToLightSource=vec3(light0.position-m*v_coord4);floatdistance=length(vertexToLightSource);lightDirection=normalize(vertexToLightSource);attenuation=1.0/(light0.constantAttenuation+light0.linearAttenuation*distance+light0.quadraticAttenuation*distance*distance);if(light0.spotCutoff<=90.0)// spotlight{floatclampedCosine=max(0.0,dot(-lightDirection,normalize(light0.spotDirection)));if(clampedCosine<cos(radians(light0.spotCutoff)))// outside of spotlight cone{attenuation=0.0;}else{attenuation=attenuation*pow(clampedCosine,light0.spotExponent);}}}vec3ambientLighting=vec3(scene_ambient);// without material color!vec3diffuseReflection=attenuation*vec3(light0.diffuse)*max(0.0,dot(normalDirection,lightDirection));// without material color!vec3specularReflection;if(dot(normalDirection,lightDirection)<0.0)// light source on the wrong side?{specularReflection=vec3(0.0,0.0,0.0);// no specular reflection}else// light source on the right side{specularReflection=attenuation*vec3(light0.specular)*vec3(mymaterial.specular)*pow(max(0.0,dot(reflect(-lightDirection,normalDirection),viewDirection)),mymaterial.shininess);}diffuseColor=ambientLighting+diffuseReflection;specularColor=specularReflection;texCoords=v_coord4;gl_Position=mvp*v_coord4;}

And the fragment shader modulates the diffuseColor with the texture color and adds the specularColor: