Diffuse light makes a surface look matte. Glossy materials, such as varnished wood, a foil-stamped title or a globe, also show specular highlights, the reflected image of the light; and in a large room, distant objects fade into fog. Both are a few lines of fragment shader. The fourteenth part of webgl-helper.js collects the section's techniques into one shader for BookNest's shelf, which the subsections take apart:
// Section 3.10: BookNest's shelf shader for GLH.lit(): two point lights with Blinn-Phong
// highlights, a glossy foil title band on each face (uFoil), and exponential-squared fog
GLH.shelfFS = `#version 300 es
precision highp float;
struct Light { vec3 position, color; };
in vec3 vPosition, vNormal; in vec2 vUV; out vec4 outColor;
uniform Light uLights[2];
uniform vec3 uColor, uAmbient, uEye, uFogColor;
uniform float uShininess, uGloss, uFoil, uFogDensity, uAlpha;
void main() {
vec3 n = normalize(vNormal), v = normalize(uEye - vPosition);
float band = step(abs(vUV.y - 0.78), 0.05); // a title band near the top
vec3 diffuse = uAmbient, specular = vec3(0.0);
for (int i = 0; i < 2; i++) {
vec3 toLight = uLights[i].position - vPosition;
float d = length(toLight), fade = clamp(1.0 - pow(d / 4.0, 4.0), 0.0, 1.0) / (d * d);
vec3 l = toLight / d, h = normalize(l + v); // Blinn's half vector
float lambert = max(dot(n, l), 0.0);
float shine = lambert > 0.0 ? pow(max(dot(n, h), 0.0), uShininess) : 0.0; // lit side
diffuse += uLights[i].color * lambert * fade;
specular += uLights[i].color * shine * fade;
}
vec3 color = uColor * diffuse + specular * (uGloss + uFoil * band);
float fog = exp(-pow(uFogDensity * distance(uEye, vPosition), 2.0)); // 1 = clear
outColor = vec4(mix(uFogColor, color, fog), uAlpha);
}`;