# IBL on Lambertian surfaces using irradiance environment map

This is the 1st stage of my real-time image-based light (IBL) renderer work. In this part, a basic asset-loading and camera system is constructed. And irradiance environment maps are used to shade diffuse surfaces.

Environment maps are commonly used as light sources in image-based light (IBL). In a non-filtered environment map, each texel represents a single discrete light source.

If the object being shaded is perfect mirror-like , only one texel on the environment map needs to be sampled for each surface point on that object. (texel sampled over the direction of specular reflection)

However, a certain range of light need to be sampled for shading other types of material (if we don’t consider refraction). For example, to shade Lambertian surfaces, the area of light source needs to be sampled is the whole upper-hemisphere over the shaded point.

$L=Kd \sum_{i \subset \Omega} max(0, D_i \cdot N) l_i$

For Lambertian surfaces, the area of light that needs to be sampled is solely determined by the surface normal. So we can create an “pre-filtered” environment map in which each texel value is $\sum_{i \subset \Omega} max(0, D_i \cdot N) l_i$. Basically it is a convolution operation over the whole environment map for each environment map texel.  Then in runtime renderinig, only one texel lookup in the prefiltered environment is needed to shade the Lambertian surfaces.

To do this convolution operation in spatial domain is very slow. Because diffuse irradiance values vary very slowly w.r.t. to normal change. We can transform the environment map into frequency space and only keep low-frequency information. A spherical function (e.g.  environment map) could be represented in frequency domain using spherical harmonic transform, and a few SH bases  is enough to represent the low frequency data of the whole environment map required by diffuse lighting. This reduces the convolution complexity from $6 \times m \times m \times 6 \times m \times m$ to $k \times 6 \times m \times m$ (m is the dimension of cubemap faces, and k is the number of preserved SH coefficients)

So what we need to do is to transform the spatial domain environment to frequency domain by SH transform, preserve only a few most significant basis coefficients, perform convolution with Lambertian reflectance function (precomputed, also represented in frequency domain)  and transform the computed environment map back to spatial representation.

CubemapGen, an environment map manipulation tool, could help you do the pre-filtering process.

Here is the result with 25 SH coefficients preserved:

And this is the rendering result of Lambertian surfaces: