Atmospheric Effects & Volume Rendering

CS 481 Lecture, Dr. Lawlor

Light interacts with large masses of air in one of two ways:landscape shading to blue sky in the distance
Eventually, you can't see the difference between distant geometry and the sky, because all the geometry's light has been scattered out, and replaced with scattered-in sky light.

Numerically, the fraction of geometry light remaining after travelling a distance t, which we'll call G(t), starts off with G(0)=1.0, and drops off at some rate until G(infinity)=0.0.  We have to assume something about the rate at which the atmosphere scatters light.  For example, if we assume the background geometry's light gets darker by 10% for every unit distance, or:
    d G / d t = -0.1

Then we can integrate to find G(t)=1.0-0.1*t.  The only problem with this is that G(10)=0.0, and then G goes negative!

A better choice is to assume that the sky scatters out 10% of the *existing* light per unit distance, or:
    d G / d t = -0.1*G(t)

The solution to this is a function that is its own derivative, G(t) = e-kt.   Then
    d G / d t  = -ke-kt
so we can read off that the scattering rate k=0.1 light fraction per unit distance.

In a raytracer, if a ray travels a distance t, then we need to darken the geometry at the end of the ray by G(t) = e-kt.  The fraction of atmosphere light scattered into the ray is 1.0-G(t).  See the underwater example codes for how this is implemented.

Typical scattering rates k for the real atmosphere are a few percent per mile for clear air; in foggy conditions this can reach several percent per foot!

Bounded Scattering Media

The simplest non-infinite scattering media is bounded within an object.  There's an easy way to compute how much scattering happens, which is to compute the t difference between the ray entry and ray exit points.  This "span" can then be plugged into the scattering equation above, so the amount of light scattered out is exp(-k*span).

Non-Uniform Scattering Media

For non-uniform scattering media, we cannot analytically solve a differential equation to figure out how much light scatters in or out, because the scattering rate changes--the constant k is not a constant!  Occasionally the scattering rate will change at only a few discrete points, so you can analytically solve between the points; or you can find a good analytic approximation for the real scattering rate; but more often the scattering rate varies arbitrarily, for example according to a 3D volume lookup table.

In this general case, the standard solution is to pick some finite dt ray step size, for example 0.01 units, and step along the ray keeping track of how the light changes.  Typically, this looks something like:
	for (float t=entry_t; t<exit_t; t+=dt) {
color = scattering_function(C+t*D,old color);
}
This is amazingly flexible, because:
Commercial volume renderers almost always use some sort of finite step size like this.