RYO* Fog #1: Texture Method
*Roll Yer Own

 

Example of using a fog texture (background is a sky_sphere which matches the fog color) Building a fog effect using textures which mimics the traditional fog in POVRay. Upside: the technique is more flexible in many respects than normal fog. Downside: the texture must be individually applied to every object in the scene and the order of object and texture transformation must be rigorously observed.
CONCEPT

 

The fog effect in POV Ray (and in most other renderers) is achieved by the simple method of replacing a fraction of an objects "regular" texture with the fog color based on the distance (d) from the point of view (or camera). Typically a fog depth or density variable (D) is also defined in some manner which controls the apparent thickness of the fog.

While linear or exponential-squared based methods are sometimes used, exponentially based fog is considered the most realistic of the three. In particular, POV Ray uses the following exponential method. Where d is the distance from the observer, D is the fog thickness control,

fog_density = 1-e-d/D

When the d is equal 0 there is no fog. At d=D the fog density is about .63 and approaches 1 as d becomes greater than D.

The fog color is blended with the obect color according to the index provided by fog_density.

final_color = fog_color*fog_density + object_color*(1 - fog_density)

In POV Ray and some other rendering engins this whole procedure is handeled internally, based on some user supplied variables, like D. Access to the actual algorithm, is limited. Hence this excercise in buliding a texture which acts as a fog effect and affords access to not only to the actual algorithm, but control over which scene elements it is applied to.

 

IMPLEMENTATION
Three elements are necessary: the distance from the camera of the point to be textured, the fog function, and the means to blend the fog color. (It is the user defined functions in POV Ray 3.5 which make this excercise feasable. Alternatively, POVman would allow building a surface shader which would do the same thing.) The length of the position vector of the point to be evaluated (relative to the camera) gives us d. However, since the x,y,z function variables (not to be confused with their vector representation outside of a function!) are absolute co-ordinates, they must be adjusted to be relative to the camera position. In POV Ray this would look something like the following.


#declare camX=cam_loc.x; 
#declare camY=cam_loc.y;
#declare camZ=cam_loc.z;

#declare d=function{sqrt(pow(x-camX, 2)+pow(y-camY,2)+pow(z-camZ,2)))}

Note that cam_loc is a declared position vector which is assigned the camera position.

The fog function which will return a value of 0 when d is zero and increases approaching a value of 1 as d becomes greater. The following is simply a translation of the already stated exponential fog equation.


#declare f_fog=function(x,y,z,D){1-exp(-d(x,y,z)/D)}

Where D is the 63% density distance and is equivalent to the "distance" keyword in a normal POV Ray fog statement.

It only remains to blend the fog color. Note one refinement which can make life easier is incasing the the process in a macro which can take the object texture as parameter. The fog texture is then blended with the object texture within the macro. To illustrate:


#declare fog_texture=texture{
 pigment{color fog_color}
 finish{diffuse 0 ambient 1}
}

#macro FOG(object_texture)
texture{
 function f_fog(x,y,z,fog_distance)
 texture_map{[0 object_texture][1 fog_texture]}
}
#end

  As I mentioned before, the order of transformations applied to an object with this fog texture is extreamely important, and therefore it is necessary to establish a good scene writing protocol beforehand. When working with this texture I used the following procedure to handle the positioning of objects.
  1. Fix the camera position: this is important since the fog is relative to the camera.
  2. Declare any object transformation: declare a transformation indentifier.
  3. Apply the object transformation.
  4. Apply object texture:this is where it can get tricky. If the texture involves a "uniform" procedural pattern like marble then you can afford to be sloppy and directly apply the mixed "fog/object texture" mix. However, if the texture is not allowed to change with object position (e.g. an image_map or an animated scene) the object texture must be transformed inversely before mixing with the fog texture.
  5. Do not apply any further transformations the the object after applying the "fog/object texture" mix.

This is only one example of a protocol, and it is best to develop one that best suits your particular situation.
 

CONCLUSION

In most instances this would be described as an academic excercise since the fog feature in POVRay does indeed function. However, the reason I started with this project was because I had a situation where I wanted to apply a fog to everything except the sky. This was not exactly possible with the regular fog feature and so the "fog texture" idea was explored. I wrote it up because I felt it had merit for the flexibility it allowed.

 

RESOURCES
 
Working With Fog: from " Introduction to Programming with Java 3D", a series of slide notes.
 
opengl notes: section "11.7 Other Atmospheric Effects"
 
Brian Hooks fog summary gleaned from the Virtual Terrain Project which you should visit anyway.


Created by Abe Madey
bullfrog@taconic.net
Reproduction permitted without express permission.
Updated Oct 12, '02