• No results found

ENVIRONMENT MAP IMPORTANCE SAMPLING

Importance sampling is used to generate directions from which we will create the shadow maps. Our goal is to find more samples in directions where the environment map intensity is large, that is, produce the sample directions proportionally to the environment map luminance. The rationale is that the brightest parts of the environment cast the most pronounced shadows, so we want to compute the shadow maps for these directions.

procedure works in the rectangular texture domain. A pixel of the environment map with texture coordinates of (u, v) corresponds to the direction whose spherical coordinates are

φ=2πu

θ=π(1-v) EQUATION 4.3.1

The Cartesian coordinates of the direction can be computed as: x=sinθ cosφ

y=sinθ sinφ

z=cosθ EQUATION 4.3.2

Before importance sampling starts, the RGB color of each pixel of the environment map is converted to luminance using the formula, Y = 0.2126 R + 0.7152 G +0.0722 B. The luminance is multiplied by the factor sin Θ, where Θ is the elevation angle corresponding to each pixel, in order to compensate for the stretching near the poles due to the latitude-longitude mapping. This step gives us a luminance map of our lighting environment that we can use for sampling.

Formally, the luminance map is an unnormalized probability mass function (PMF). In general, a PMF is just a set of probabilities that a number of events will take place. In our case an event means choosing a particular pixel of the 2D environment map in the sampling procedure. In order to call our luminance map a PMF, we should first normalize it by scaling every pixel’s value such that all pixels sum to one. However, we can skip this costly explicit normalization step. Instead, we perform an implicit normalization by rescaling the random numbers used for sampling by the sum of all environment map pixels.

Our sampling problem is defined in 2D, but we can easily simplify it to sampling two 1D functions: First, we pick a row of the environment map and, second, we pick a pixel within the selected row. To select the row, we use the marginal PMF, which is simply the sum of luminances for each row of the environment map. This way, rows with brighter pixels are more likely to be sampled than rows with dim pixels. After selecting a row, we pick a pixel according to the 1D PMF given by the pixel luminances in the selected row. This concept is illustrated in Figure 4.3.2.

Now all we need to perform sampling is a procedure to randomly pick an element according to a 1D PMF. Imagine that you stack the probabilities in the PMF next to each other as shown in Figure 4.3.3. If we choose a random number, where there exists an equal likelihood that any value between 0 and 1 will be produced, then more numbers will map to the higher-probability item, the third probability in our example, and thus we will sample that direction more often. The stacking of the PMF is formally known as the discrete cumulative distribution function (CDF).

FIGURE 4.3.2 Sampling from a 2D probability mass function (PMF). First, a row is selected using the 1D marginal PMF (given by the sum of the probabilities in each row). Second, a pixel in the selected row is picked using the 1D PMF for the selected row.

FIGURE 4.3.3 The discrete cumulative distribution function (CDF). By stacking the PMF of each column (left), we obtain a CDF (right). Using a random number u between zero and one, we can find the column whose CDF range contains u. Continuing this process, we get a distribution of column samples proportional to the PMF. In this case, since the third column is larger than the

others, we will have more samples from that column.

Sampling from the PMF thus reduces to generating a random number u uniformly distributed between zero and the sum of all probabilities, and finding the first entry in the CDF larger than u. Binary search can be used for this purpose.

It would be undesirable if two or more samples were generated very close to each other, which could easily happen with purely random sampling. To prevent this sample clumping, we generate quasi-random numbers using the folded Hammersley sequence

[Pharr04], which provides good sample distributions. Let us now summarize the sampling procedure.

1. Generate the conditional CDF for each row of the environment map by accumulating the pixel luminances. 2. Generate the marginal CDF by accumulating the values of the last pixel of each row’s conditional CDF.

samples we want to generate. 4. For each sample direction i:

a. Pick a row by finding the first entry of the marginal CDF larger than ξ0,i * Σ, where the normalizing factor Σ is the sum of all pixels in the PMF map.

b. Use the second value in the tuple, ξ1, i, to pick a column in the row.

c. Compute the sample direction using Equations 4.3.1 and 4.3.2.

The end result of the above procedure is a set of sample directions generated proportionally to the environment map luminance.

Figure 4.3.4 shows the resulting distribution of samples for two environment maps.

FIGURE 4.3.4 Sample distribution for two environment maps (St. Peters Cathedral and Pisa).

V

ISIBILITY

M

AP

G

ENERATION

In order to capture visibility along our sample directions, we render shadow maps. We set an orthographic camera on a bounding sphere of the scene in the sample direction and render the scene into a depth buffer.

We only have a few shadow maps at our disposal, due to the limited computation resources. As we will see in the sections “Rendering Shadows on Diffuse Surfaces” and “Rendering Shadows on Glossy Surfaces,” we need to evaluate the visibility at any point for any direction to render images with shadows. Therefore, we interpolate the visibility information in the shadow maps to any direction. To this end, we exploit the good directional interpolation properties of spherical harmonics (SH) and convert the shadow maps to an SH-based visibility map.

The visibility map is simply a texture of SH coefficients mapped to scene meshes. For that reason, the meshes must be equipped with a smooth, nonoverlapping parameterization (i.e., texture coordinates). Each mesh in the scene has its own visibility map. Each texel of the visibility map stores 16 spherical harmonic coefficients that approximate the visibility function for each direction around the texel position (directions pointing inside the object have zero visibility). The visibility function at point p is a spherical function (i.e., it takes a direction as an argument) defined as follows:

FIGURE 4.3.5 illustrates the visibility function for a simple scene.

In the rest of this section, we describe the construction of the visibility map. First, we give a brief introduction to spherical harmonics. After that we describe the fitting procedure used to find the SH coefficients in the visibility map from the shadow maps. Finally, we describe the filtering procedure used to alleviate occasional aliasing artifacts caused by the use of low-resolution shadow maps. The use of the visibility map for shadow rendering is described in the subsequent sections.