First of all, you should think of your light-source image as an environment map, such as you might use for reflection mapping. IBL is, after all, just a diffused version of a reflection map, and a reflection map is functionally the same as a dense cloud of point lights.
Quote:
What is the "solid angle", and how is it relevant? How do I derive it?
The 'solid angle' is a measure of the area of any region or feature in your environment map, after it's transformed into spherical space. It's usually measured in steradians (sr), which are dimensionless, like degrees. Some examples: the solid angle of a whole sphere is 4pi sr, a hemisphere such as the visible sky is 2pi sr, and the moon is about 0.00006 sr (about a hundred-thousandth of the sky).
If you're sampling your map by brute force or monte carlo integration, you don't really need to think much about this, as every sample will subtend the same infinitesimal solid angle. By the same token, you usually don't need to think about
area when you're sampling a regular 2D texture.
Quote:
In the case of a cubemap/spheremap, how do I derive the normals for each pixel?
The same way as if you're sampling a reflection map - except that you don't need to consider the view vector or the reflection vector. You already have a 3D unit vector to sample a 2D environment map, right? That vector is the normal you're looking for.
Quote:If the basic approach generates data for a Phong exponent of 1, how do I generate data for different specular powers?
Nope - the basic approach generates data for a
Lambertian shading model (or the Lambertian term of a Phong model), which is view-independent, which is why it's possible to bake image-based diffuse lighting in the first place. The Phong specular term is always view-dependent, and that's not what you're baking.
For very high powers (eg:100), the original environment map (sampled via a reflection vector) is all the data you need for the specular term. For lower powers, you can just supersample the environment map as though you were raytracing 'glossy reflections' - jittering the reflection vector - but without testing rays against geometry. You could treat each sample as a Phong (specular) light-source, or you could use a ready-made poisson distribution of sample offsets and weights.
If realtime performance is critical, you can simply apply a gaussian blur to your environment map (in spherical space, if you can) and then take fewer samples - or even a single sample of a heavily-blurred map.
There's no physically-correct way of doing this. Phong is, at best, a gross approximation of the real effect. What you'll find, though, is that there's a whole continuum of strategies
between reflection mapping and diffuse IBL, that differ only in how & when samples are integrated.
Quote:How do I normalize the final values to the range [0,1] to minimize banding in low-precision storage? Do I just find the brightest value and divide every other value by it?
To avoid having to scale or clamp your values, given that you're probably not using your storage format's alpha channel, you could store a multiplier or exponent in each texel's alpha, such as in the Radiance RGBE format. But really, unless you're targeting old-fashioned hardware or software libraries, you're better off using a higher-precision storage format like half-float OpenEXR. This is, after all, the year 2000 or something.
Quote: So, the specular lighting ends up dominating the diffuse lighting.
How should I change the way I handle specular IBL to make it look good?
For anything metallic, you only really need specular lighting. Tint it if you're rendering a coloured metal like brass or copper. Supersampling is your best bet if you need effects like anisotropic reflections, like for brushed or lathed metal.
For anything smooth and non-metallic (plastic, marble, skin etc.), you need a diffuse sample and a specular sample, and then you blend between them with Fresnel's equation for reflection. This will realistically accentuate reflections at glancing angles. For transparent or translucent materials, replace the diffuse term with the refraction/translucency term. By all means tint & texture the diffuse sample, but don't tint the specular sample - leave its chrominance unmodified - just
mask it where necessary.
That's enough to cover 99% of all the materials you see around you. For realism, trust the Fresnel equation but keep its IOR between about 1.3 and 1.9, and whenever you're estimating a diffuse value or colour,
halve it. For example the 'whites' of your eyes are actually 50% grey, but they exhibit full Fresnel reflection with an IOR of 1.33.