A simple fog effect can be achieved by mixing the color of each fragment with a constant fog color. The amount of influence of the fog color is determined by the distance from the camera. We could use either a linear relationship between the distance and the amount of fog color, or we could use a non-linear relationship such as an exponential one.
The following figure shows four teapots rendered with a fog effect produced by mixing the fog color in a linear relationship with distance.
To define this linear relationship we can use the following equation:
In the preceding equation, dmin is the distance from the eye where the fog is minimal (no fog contribution), and dmax is the distance where the fog color obscures all other colors in the scene. The variable z
represents the distance from the eye. The value f
is the fog factor. A fog factor of zero represents 100 percent fog, and a factor of one represents no fog. Since fog typically looks thickest at large distances, the fog factor is minimal when |z| is equal to dmax, and maximal when |z| is equal to dmin.
Start with the same vertex shader from the Using per-fragment shading for improved realism recipe. Your OpenGL program must set the values for all uniform variables defined in that vertex shader as well as the fragment shader shown in the following section.
To create a shader that produces a fog-like effect, use the following code for the fragment shader:
in vec3 Position; in vec3 Normal; struc tLightInfo { vec4 position; vec3 intensity; }; uniform LightInfo Light; struct FogInfo { float maxDist; float minDist; vec3 color; }; uniform FogInfo Fog; uniform vec3 Kd; // Diffuse reflectivity uniform vec3 Ka; // Ambient reflectivity uniform vec3 Ks; // Specular reflectivity uniform float Shininess; // Specular shininess factor layout( location = 0 ) out vec4 FragColor; vec3 ads( ) { // … The ADS shading algorithm } void main() { float dist = abs( Position.z ); float fogFactor = (Fog.maxDist - dist) / (Fog.maxDist - Fog.minDist); fogFactor = clamp( fogFactor, 0.0, 1.0 ); vec3 shadeColor = ads(); vec3 color = mix( Fog.color, shadeColor, fogFactor ); FragColor = vec4(color, 1.0); }
In this shader, the ads
function is exactly the same as the one used in the recipe Using the halfway vector for improved performance. The part of this shader that deals with the fog effect lies within the main
function.
The uniform variable Fog
contains the parameters that define the extent and color of the fog. The minDist
field is the distance from the eye to the fog's starting point, and maxDist
is the distance to the point where the fog is maximal. The color
field is the color of the fog.
The dist
variable is used to store the distance from the surface point to the eye position. The z
coordinate of the position is used as an estimate of the actual distance. The fogFactor
variable is computed using the preceding equation. Since dist
may not be between minDist
and maxDist
, we clamp the value of fogFactor
to be between zero and one.
We then call the ads
function to evaluate the basic ADS shading model. The result of this is stored in the shadeColor
variable.
Finally, we mix shadeColor
and Fog.color
together based on the value of fogFactor
, and the result is used as the fragment color.
In this recipe, we used a linear relationship between the amount of fog color and the distance from the eye. Another choice would be to use an exponential relationship. For example, the following equation could be used:
In the above equation, d represents the density of the fog. Larger values would create "thicker" fog. We could also square the exponent to create a slightly different relationship (a faster increase in the fog with distance).
In the above code, we used the absolute value of the z coordinate as the distance from the camera. This may cause the fog to look a bit unrealistic in certain situations. To compute a more precise distance, we could replace the line:
float dist = abs( Position.z );
with the following:
float dist = length( Position.xyz );
Of course, the latter version requires a square root, and therefore would be a bit slower in practice.
3.149.254.35