5.3. Common Functions
Common functions can be used within either vertex shaders or fragment shaders. These functions all operate in a component-wise fashion (see Table 5.3) The description column specifies the operation on each component.
Aside from their general usefulness as math functions, many of these functions are useful in creating interesting shaders, as we see in subsequent chapters. The abs function can ensure that a particular function never produces negative values. It can also introduce a discontinuity in an otherwise smooth function. As we see in Section 15.5, this property of the abs function is used to introduce discontinuities in a noise function to produce an effect that looks like turbulence. A graphical representation of the abs function is shown in Figure 5.2.
Figure 5.2. The abs function
The sign function simply maps the incoming value to -1, 0, or 1, depending on its sign. This results in a discontinuous function, as shown in Figure 5.3.
Figure 5.3. The sign function
The floor function produces a discontinuous stair-step pattern, as shown in Figure 5.4. The fractional part of each incoming value is dropped, so the output value is always the integer value that is closest to but less than or equal to the input value.
Figure 5.4. The floor function
The ceil function is almost the same as the floor function, except that value returned is always the integer value that is closest to but greater than or equal to the input value. This function is shown in Figure 5.5. As you can see, this function looks the same as Figure 5.4 except that the output values are shifted up by one. (Although ceil and floor always produce integer values, the functions are defined to return floating-point data types.)
Figure 5.5. The ceil function
The fract function produces a discontinuous function where each segment has a slope of 1.0 (see Figure 5.6).
Figure 5.6. The fract function
The mod function is very similar to fract. In fact, if we divide the result of mod(x, y) by y, the result is very nearly the same. The only difference is the period of the discontinuous segments (see Figure 5.7).
Figure 5.7. The periodic function mod(x, y)
clamp(x, 0.0, 1.0);
which clamps the variable x to the range [0,1]. Because two comparisons are necessary for this function, you should use it only when there is a chance that the tested value could be outside either end of the specified range. For the min and max functions, only one comparison is necessary. If you know a value will not be less than 0, using
will likely be faster and may use fewer machine instructions than
clamp(x, 0.0, 1.0);
because there is no point in testing to see whether the final value is less than 0. Keep in mind that there is no need to clamp the final color and depth values computed by a fragment shader because they are clamped automatically by the back-end fixed functionality processing.
The min, max, and clamp functions are shown in Figure 5.8, Figure 5.9, and Figure 5.10. The min(x, y) function has a slope of 1 where x is less than y, and a slope of 0 where x is greater than y. This function is often used to put an upper bound on a value, for instance, to make sure the computed result never exceeds 1.0.
Figure 5.8. The min function
Figure 5.9. The max function
Figure 5.10. The clamp function
The max(x, y) function has a slope of 0 where x is less than y, and a slope of 1 where x is greater than y. This function is often used to put a lower bound on a value, for instance, to make sure the computed result never goes below 0.
The clamp(x, minVal, maxVal) function has a slope of 0 where x is less than minVal and where x is greater than maxVal, and it has a slope of 1 in between where x is greater than minVal and less than maxVal. It is functionally equivalent to the expression min(max(x, minVal), maxVal).
Figure 5.11. The step function
The smoothstep function (see Figure 5.12) is useful in cases in which you want a threshold function with a smooth transition. For the case in which t is a float, this is equivalent to
float t; t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); return t * t * (3.0 - 2.0 * t);
Figure 5.12. The smoothstep function
The cases for vec2, vec3, and vec4 differ from the preceding example only in the data type used to declare t.