How it works...

The buildOffsetTex function creates our three-dimensional texture of random offsets. The first parameter, texSize, defines the width and height of the texture. To create the preceding images, I used a value of 8. The second and third parameters, samplesU and samplesV, define the number of samples in the u and v directions. I used a value of 4 and 8, respectively, for a total of 32 samples. The u and v directions are arbitrary axes that are used to define a grid of offsets. To understand this, take a look at the following diagram:

The offsets are initially defined to be centered on a grid of size samplesU x samplesV (4 x 4 in the preceding diagram). The coordinates of the offsets are scaled such that the entire grid fits in the unit cube (side length 1) with the origin in the lower-left corner. Then, each sample is randomly jittered from its position to a random location inside the grid cell. Finally, the jittered offsets are warped so that they surround the origin and lie within the circular grid shown on the right.

The last step can be accomplished by using the v coordinate as the distance from the origin and the u coordinate as the angle scaled from 0 to 360. The following equations should do the trick:

Here, w is the warped coordinate. What we are left with is a set of offsets around the origin that are a maximum distance of 1.0 from the origin. Additionally, we generate the data such that the first samples are the ones around the outer edge of the circle, moving inside toward the center. This will help us avoid taking too many samples when we are working completely inside or outside of the shadow.

Of course, we also pack the samples in such a way that a single texel contains two samples. This is not strictly necessary, but is done to conserve memory space. However, it does make the code a bit more complex.

Within the fragment shader, we start by computing the ambient component of the shading model separately from the diffuse and specular components. We access the offset texture at a location based on the fragment's screen coordinates (gl_FragCoord). We do so by taking the modulus of the fragment's position and the size of the offset texture. The result is stored in the first two components of offsetCoord. This will give us a different set of offsets for each nearby pixel. The third component of offsetCoord will be used to access a pair of samples. The number of samples is the depth of the texture divided by two. This is stored in samplesDiv2. We access the sample using the texelFetch function. This function allows us to access a texel using the integer texel coordinates rather than the usual normalized texture coordinates in the range 0-1.

The offset is retrieved and multiplied by Radius and the w component of ShadowCoord. Multiplying by Radius simply scales the offsets so that they range from 0.0 to Radius.  Typically, we want the radius to represent a small region in texel space, so a value like 5/width (where width is the width of the shadow map) would be appropriate. We multiply by the w component because ShadowCoord is still a homogeneous coordinate, and our goal is to use offsets to translate the ShadowCoord. In order to do so properly, we need to multiply the offset by the w component. Another way of thinking of this is that the w component will be cancelled when perspective division takes place.

Next, we use offsets to translate ShadowCoord and access the shadow map to do the depth comparison using textureProj. We do so for each of the two samples stored in the texel, once for the first two components of offsets and again for the last two. The result is added to sum.

The first loop repeats this for the first eight samples. If the first eight samples are all 0.0 or 1.0, then we assume that all of the samples will be the same (the sample area is completely in or out of the shadow). In that case, we skip the evaluation of the rest of the samples. Otherwise, we evaluate the following samples and compute the overall average. Finally, the resulting average (shadow) is used to attenuate the diffuse and specular components of the lighting model.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.23.30