20.6. CloudsCloud lighting is dominated by scattering that is similar to atmospheric scattering, but much more complex. Light is scattered by the water vapor within the cloud. Low-density regions let most light through; high-density regions absorb or scatter most of the light that passes through. Some real clouds are shown in the photo in Color Plate 37D. These clouds are lit by vertical sunlight. In simplistic terms, the lighting effects can be explained as follows. Photons enter the cloud, and if they hit a water vapor molecule, they are scattered in a random direction. Therefore, parts of cloud that are directly illuminated by the sun are brightlots of sunlight reaches them, so proportionally more light is scattered toward the viewer. However, the clouds are dense and so light cannot penetrate far into the body of the cloud; little or no light reaches the bottom of the clouds and so they are dark. For the same reason, light from bright regions on the far side of the cloud body is blocked. At the fringes of the clouds, the clouds are less dense. So, sunlight scattered from those regions toward the eye is not completely blocked. For this reason, the edges of clouds tend to be bright. Figure 20.11 illustrates this effect. The cloud edge is light gray where the sunlight strikes; these are the bright areas. Light is scattered in all directions but is absorbed by the cloud body, depending how far it travels through the cloud and how dense the cloud is. Figure 20.11. Sunlight striking a cloud
The clouds in RealWorldz simulate some of these effects. Color Plate 37G demonstrates the self-shadowingthe darkening is much more subtle than it is in the photograph of real clouds. Color Plate 37H demonstrates the edge lighting. In RealWorldz, the clouds and smoke are rendered with a collection of 16 different billboard images generated by ray-marching a 3D monofractal. For each texel of the billboard image, an opacity and surface normal were generated. The alpha and color channels for a single billboard image are shown in Color Plate 37F. The upper image is the alpha channel; it stores the opacity. Black is 0, indicating complete transparency; white is 1.0, indicating complete opacity. The lower image is the RGB color channel holding the packed normal. The normal is unpacked in the usual waysubtraction of 0.5 and multiplication by 2.0. The opacity was calculated by numerical integration of the ray through the 3D monofractal. The surface normal was established by determination of the point at which the ray integral rose above a certain (small) value; corresponding points were found for rays in slightly different directions and a plane fitted to those points. The surface normal was defined to be normal to that plane. The surface normal is used to estimate whether the pixel is facing the sun; this provides the brightening of regions facing the sun and the self-shadowing effect. The opacity determines how much the cloudlet occludes objects behind itthe cloudlets are drawn in far-to-near order, so near cloudlets occlude more distant cloudlets. The fragment shader code to calculate the color and alpha of the cloudlet is given here. cloudletNormal is the unpacked normal vector; cloudletOpacity is the opacity. cloudletLightDir is the sunlight vector, transformed into the space in which the cloudlet normals are stored. alphaScalar is a value in the range [0,1] provided by the vertex shader: Normally it is 1.0, but 0 makes the cloudlet completely transparent. float d = 0.95 +(dot(cloudletLightDir, screenLightDir) * 0.3 * cloudletOpacity); vec3 baseCloudColor = vec3(1.0, 0.93, 0.9); gl_FragColor.rgb = d * baseCloudColor; gl_FragColor.a = cloudletOpacity * alphaScalar; Cloudlets that are too near or too far from the viewer are not drawn. So that cloudlets do not abruptly disappear when they leave the visible range, they become progressively more transparent as they near the boundaries of the visible region. This fadeout is implemented by the vertex shader calculating the cloudlet distance; alphaScalar takes the value 0 if the cloudlet is at the boundaries of the visible region, rising to 1.0 in the interior of the visible region. |