Chapter 5. Built-in Functions

This chapter provides the details of the functions that are defined as part of the OpenGL Shading Language. Feel free to skip ahead to the next chapter if you want to get down to the nitty-gritty of writing your own shaders. This chapter can be useful as a reference after you are well on your way to writing OpenGL shaders for your own application.

The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar and vector operations. The reasons for providing built-in functions for the OpenGL Language include

  • Making shaders simpler to develop and easier to understand and maintain.

  • Exposing some necessary hardware functionality in a convenient way such as accessing a texture map. The language for these functions cannot be emulated by a shader.

  • Representing a trivial operation (clamp, mix, etc.) that is simple for a user to write but that is common and may have direct hardware support. Providing a built-in function makes it much easier for the compiler to map such expressions to complex hardware instructions.

  • Representing an operation that graphics hardware is likely to accelerate at some point. The trigonometry functions fall into this category.

Many of the functions are similar to the same named ones in common C libraries, but they support vector input as well as the more traditional scalar input. Because the OpenGL Shading Language supports function overloading, the built-in functions usually have several variants, all with the same name. The difference in the functions is in the type of arguments and the type of the value returned. Quite a few of the built-in functions have four variants: one that takes float parameters and returns a float, one that takes vec2 parameters and returns a vec2, one that takes vec3 parameters and returns a vec3, and one that takes vec4 parameters and returns a vec4.

Whenever possible, you should use the built-in functions rather than do the equivalent computations in your own shader code. It is expected that the built-in functions will be implemented in an optimal way, perhaps even supported directly in hardware. Almost all the built-in functions can be used in either a vertex shader or a fragment shader, but a few are available only for a specific type of shader. You can write a shader to replace a built-in function with your own code simply by redeclaring and defining the same function name and argument list.

Graphical representations of some of the functions are shown for clear illustration. The functions are generally simple ones, and most readers would have no trouble constructing such diagrams themselves. But as we see in later chapters, many of the built-in functions can be used in unconventional ways to achieve interesting effects in shaders. When you are developing a shader, it is often helpful to draw a simple function diagram to clearly envision the value of a variable at a particular spot in a shader. By seeing a pictorial representation of some of these functions, you may find it easier to draw such diagrams yourself and to gain some insight about how you might use them in procedural shaders. Some common uses for these functions are pointed out along the way, and some are illustrated by shader examples in the later chapters of this book.

Angle and Trigonometry Functions

Trigonometry functions can be used within either vertex shaders or fragment shaders. Function parameters specified as angle are assumed to be in units of radians. In no case do any of these functions result in a divide-by-zero error. If the divisor of a ratio is 0, results are undefined.

These functions all operate component-wise (see Table 5.1). The description column specifies the operation on each component.

Table 5.1. Angle and trigonometry functions

Syntax

Description

float radians (float degrees) vec2 radians (vec2 degrees) vec3 radians (vec3 degrees) vec4 radians (vec4 degrees)

Converts degrees to radians and returns the result, i.e., result = π/180 · degrees.

float degrees (float radians) vec2 degrees (vec2 radians) vec3 degrees (vec3 radians) vec4 degrees (vec4 radians)

Converts radians to degrees and returns the result, i.e., result = 180/π · radians.

float sin (float radians) vec2 sin (vec2 radians) vec3 sin (vec3 radians) vec4 sin (vec4 radians)

The standard trigonometric sine function. The values returned by this function range from [−1,1].

float cos (float radians) vec2 cos (vec2 radians) vec3 cos (vec3 radians) vec4 cos (vec4 radians)

The standard trigonometric cosine function. The values returned by this function range from [−1,1].

float tan (float radians) vec2 tan (vec2 radians) vec3 tan (vec3 radians) vec4 tan (vec4 radians)

The standard trigonometric tangent function.

float asin (float x) vec2 asin (vec2 x) vec3 asin (vec3 x) vec4 asin (vec4 x)

Arc sine. Returns an angle whose sine is x. The range of values returned by this function is [−π/2, π/2]. Results are undefined if |x| > 1.

float acos (float x) vec2 acos (vec2 x) vec3 acos (vec3 x) vec4 acos (vec4 x)

Arc cosine. Returns an angle whose cosine is x. The range of values returned by this function is [0, π]. Results are undefined if |x| > 1.

float atan (float y, float x) vec2 atan (vec2 y, vec2 x) vec3 atan (vec3 y, vec3 x) vec4 atan (vec4 y, vec4 x)

Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y determine what quadrant the angle is in. The range of values returned by this function is [−π, π]. Results are undefined if x and y are both 0.

float atan (float y_over_x) vec2 atan (vec2 y_over_x) vec3 atan (vec3 y_over_x) vec4 atan (vec4 y_over_x)

Arc tangent. Returns an angle whose tangent is y_over_x. The range of values returned by this function is [−π/2, π/2].

In addition to their usefulness as trigonometric functions, sin and cos can be used in a variety of ways as the basis for a smoothly varying function with no cusps or discontinuities (see Figure 5.1). Such a function can be used to model waves on the surface of an object, to change periodically between two materials, to introduce a rocking motion to an object, or to achieve many other effects.

The sin and cos functions

Figure 5.1. The sin and cos functions

Exponential Functions

Exponential functions can be used within either vertex shaders or fragment shaders. These all operate component-wise (see Table 5.2). The description column specifies the operation on each component.

Table 5.2. Exponential functions

Syntax

Description

float pow (float x, float y) vec2 pow (vec2 x, vec2 y) vec3 pow (vec3 x, vec3 y) vec4 pow (vec4 x, vec4 y)

Returns x raised to the y power, i.e., xy. Results are undefined if x < 0. Results are undefined if x = 0 and y = 0.

float exp (float x) vec2 exp (vec2 x) vec3 exp (vec3 x) vec4 exp (vec4 x)

Returns the natural exponentiation of x, i.e., ex.

float log (float x) vec2 log (vec2 x) vec3 log (vec3 x) vec4 log (vec4 x)

Returns the natural logarithm of x, i.e., returns the value y, which satisfies the equation x = ey. Results are undefined if x <= 0.

float exp2 (float x) vec2 exp2 (vec2 x) vec3 exp2 (vec3 x) vec4 exp2 (vec4 x)

Returns 2 raised to the x power, i.e., 2x.

float log2 (float x) vec2 log2 (vec2 x) vec3 log2 (vec3 x) vec4 log2 (vec4 x)

Returns the base 2 log of x, i.e., returns the value y, which satisfies the equation x = 2y. Results are undefined if x <= 0.

float sqrt (float x) vec2 sqrt (vec2 x) vec3 sqrt (vec3 x) vec4 sqrt (vec4 x)

Returns the positive square root of x. Results are undefined if x < 0.

float inversesqrt (float x) vec2 inversesqrt (vec2 x) vec3 inversesqrt (vec3 x) vec4 inversesqrt (vec4 x)

Returns the reciprocal of the positive square root of x. Results are undefined if x <= 0.

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.

Table 5.3. Common functions

Syntax

Description

float abs (float x) vec2 abs (vec2 x) vec3 abs (vec3 x) vec4 abs (vec4 x)

Returns x if x >= 0; otherwise, it returns −x.

float sign (float x) vec2 sign (vec2 x) vec3 sign (vec3 x) vec4 sign (vec4 x)

Returns 1.0 if x > 0, 0.0 if x = 0, or −1.0 if x < 0.

float floor (float x) vec2 floor (vec2 x) vec3 floor (vec3 x) vec4 floor (vec4 x)

Returns a value equal to the nearest integer that is less than or equal to x.

float ceil (float x) vec2 ceil (vec2 x) vec3 ceil (vec3 x) vec4 ceil (vec4 x)

Returns a value equal to the nearest integer that is greater than or equal to x.

float fract (float x) vec2 fract (vec2 x) vec3 fract (vec3 x) vec4 fract (vec4 x)

Returns xfloor (x).

float mod (float x, float y) vec2 mod (vec2 x, float y) vec3 mod (vec3 x, float y) vec4 mod (vec4 x, float y)

Modulus. Returns xy * floor (x/y) for each component in x using the floating-point value y.

vec2 mod (vec2 x, vec2 y) vec3 mod (vec3 x, vec3 y) vec4 mod (vec4 x, vec4 y)

Modulus. Returns xy * floor (x/y) for each component in x using the corresponding component of y.

float min (float x, float y) vec2 min (vec2 x, vec2 y) vec3 min (vec3 x, vec3 y) vec4 min (vec4 x, vec4 y)

Returns y if y < x; otherwise, it returns x.

vec2 min (vec2 x, float y) vec3 min (vec3 x, float y) vec4 min (vec4 x, float y)

Returns minimum of each component of x compared with the floating-point value y.

float max (float x, float y) vec2 max (vec2 x, vec2 y) vec3 max (vec3 x, vec3 y) vec4 max (vec4 x, vec4 y)

Returns y if x < y; otherwise, it returns x.

vec2 max (vec2 x, float y) vec3 max (vec3 x, float y) vec4 max (vec4 x, float y)

Returns maximum of each component of x compared with the floating-point value y.

float clamp (float x, float minVal, float maxVal) vec2 clamp (vec2 x, float minVal, float maxVal) vec3 clamp (vec3 x, float minVal, float maxVal) vec4 clamp (vec4 x, float minVal, float maxVal)

Returns min (max (x, minVal), maxVal) for each component in x using the floating-point values minVal and maxVal. Results are undefined if minVal > maxVal.

vec2 clamp (vec2 x, vec2 minVal, vec2 maxVal) vec3 clamp (vec3 x, vec3 minVal, vec3 maxVal) vec4 clamp (vec4 x, vec4 minVal, vec4 maxVal)

Returns the component-wise result of min (max (x, minVal), maxVal). Results are undefined if minVal > maxVal.

float mix (float x, float y, float a) vec2 mix (vec2 x, vec2 y, float a) vec3 mix (vec3 x, vec3 y, float a) vec4 mix (vec4 x, vec4 y, float a)

Returns x * (1.0 – a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0,1].

vec2 mix (vec2 x, vec2 y, vec2 a) vec3 mix (vec3 x, vec3 y, vec3 a) vec4 mix (vec4 x, vec4 y, vec4 a)

Returns the component-wise result of x * (1.0 – a) + y * a, i.e., the linear blend of vectors x and y using the vector a. The value for a is not restricted to the range [0,1].

float step (float edge, float x) vec2 step (vec2 edge, vec2 x) vec3 step (vec3 edge, vec3 x) vec4 step (vec4 edge, vec4 x)

Returns 0 if x < edge; otherwise, it returns 1.0.

float smoothstep (float edge0, float edge1, float x) vec2 smoothstep (vec2 edge0, vec2 edge1, vec2 x) vec3 smoothstep (vec3 edge0, vec3 edge1, vec3 x) vec4 smoothstep (vec4 edge0, vec4 edge1, vec4 x)

Returns 0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth Hermite interpolation between 0 and 1 when edge0 < x < edge1. Results are undefined if edge0 >= edge1.

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.

The abs function

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.

The sign function

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.

The floor function

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.)

The ceil function

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).

The fract function

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).

The periodic function mod(x, y)

Figure 5.7. The periodic function mod(x, y)

The clamp function is useful for making sure that a value is within a particular range. A common operation is

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

min(x, 1.0);

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.

The min function

Figure 5.8. The min function

The max function

Figure 5.9. The max function

The clamp 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).

The step function creates a discontinuous jump at an arbitrary point (see Figure 5.11). We use this function to create a simple procedural brick shader in Chapter 6.

The step function

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);
The smoothstep function

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.

Geometric Functions

Except for ftransform, geometric functions can be used within either vertex shaders or fragment shaders. These functions operate on vectors as vectors, not in a component-wise fashion (see Table 5.4).

Table 5.4. Geometric functions

Syntax

Description

float length (float x) float length (vec2 x) float length (vec3 x) float length (vec4 x)

Returns the length of vector x, i.e., sqrt(x[0] * x[0] + x[1] * x[1] + . . .).

float distance (float p0, float p1) float distance (vec2 p0, vec2 p1) float distance (vec3 p0, vec3 p1) float distance (vec4 p0, vec4 p1)

Returns the distance between p0 and p1, i.e., length(p0p1).

float dot (float x, float y) float dot (vec2 x, vec2 y) float dot (vec3 x, vec3 y) float dot (vec4 x, vec4 y)

Returns the dot product of x and y, i.e., result = x[0] * y[0] + x[1] * y[1] + . . ..

vec3 cross (vec3 x, vec3 y)

Returns the cross product of x and y, i.e., result[0] = x[1] * y[2] - y[1] * x[2] result[1] = x[2] * y[0] - y[2] * x[0] result[2] = x[0] * y[1] - y[0] * x[1]

float normalize (float x) vec2 normalize (vec2 x) vec3 normalize (vec3 x) vec4 normalize (vec4 x)

Returns a vector in the same direction as x but with a length of 1.

vec4 ftransform()

For vertex shaders only. This function ensures that the incoming vertex position is transformed in a way that produces exactly the same result as would be produced by OpenGL’s fixed functionality transform. This function typically computes the value for gl_Position.

float faceforward (float N, float I, float Nref) vec2 faceforward (vec2 N, vec2 I, vec2 Nref) vec3 faceforward (vec3 N, vec3 I, vec3 Nref) vec4 faceforward (vec4 N, vec4 I, vec4 Nref)

If dot (Nref, I) < 0.0, return N; otherwise, return −N.

float reflect (float I, float N) vec2 reflect (vec2 I, vec2 N) vec3 reflect (vec3 I, vec3 N) vec4 reflect (vec4 I, vec4 N)

For the incident vector I and surface orientation N, returns the reflection direction: result = I – 2.0 * dot (N, I) * N N must already be normalized to achieve the desired result. I need not be normalized.

float refract (float I, float N, float eta) vec2 refract (vec2 I, vec2 N, float eta) vec3 refract (vec3 I, vec3 N, float eta) vec4 refract (vec4 I, vec4 N, float eta)

For the incident vector I and surface normal N and the ratio of indices of refraction eta, returns the refraction vector. The returned result is computed as

k = 1.0 − eta * eta *
      (1.0dot (N, I) * dot (N, I))
if (k < 0.0)
    result = 0.0;
    // result type is float or vec2/3/4
 else
   result = eta * I−
              (eta * dot (N, I) * sqrt (k)) * N

The float version of the distance function may not seem terribly useful (it’s the same as the absolute value of the difference), but the vector forms compute the Euclidean distance between two points. Similarly, the float version of normalize always returns 1, and the float version of length always returns the absolute value of the input argument as the result. These scalar forms are useful in that the data type of the argument can be changed without the need to change the code that calls the built-in function.

You can use the ftransform function to transform the incoming vertex position:

gl_Position = ftransform()

It transforms the value of gl_Vertex by the current modelview-projection matrix to produce a value for gl_Position that is identical to what would have been computed by the fixed functionality pipeline. This function should be used, for example, when an application is rendering the same geometry in separate passes, where one pass uses the fixed functionality path to render and another pass uses the programmable processors.

Matrix Functions

Matrix functions can be used within either vertex shaders or fragment shaders (see Table 5.5).

Table 5.5. Matrix functions

Syntax

Description

mat2 matrixCompMult (mat2 x, mat2 y) mat3 matrixCompMult (mat3 x, mat3 y) mat4 matrixCompMult (mat4 x, mat4 y)

Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product of x[i][j] and y[i][j]. Note: To get linear-algebraic matrix multiplication, use the multiply operator (*).

These functions produce the component-wise multiplication of two matrices. For instance, the result of calling matrixCompMult with two 3D matrices x and y looks like this:

mat3 x, y, newmat;
. . .
newmat = matrixCompMult(x, y);
Matrix functions

This is not usually what you want if you are using matrices to represent transformation steps. In this case, you would use the multiply operator (*) to perform the linear-algebraic matrix multiplication

mat3 x, y, newmat;
. . .
newmat = x * y;

which performs the following operation:

Matrix functions

Vector Relational Functions

Relational and equality operators (<, <=, >, >=, ==, !=) are defined to produce scalar Boolean results and can be used within either vertex shaders or fragment shaders. For vector results, use the built-in functions in Table 5.6.

Table 5.6. Vector relational functions

Syntax

Description

bvec2 lessThan(vec2 x, vec2 y) bvec3 lessThan(vec3 x, vec3 y) bvec4 lessThan(vec4 x, vec4 y) bvec2 lessThan(ivec2 x, ivec2 y) bvec3 lessThan(ivec3 x, ivec3 y) bvec4 lessThan(ivec4 x, ivec4 y)

Returns the component-wise compare of x < y.

bvec2 lessThanEqual(vec2 x, vec2 y) bvec3 lessThanEqual(vec3 x, vec3 y) bvec4 lessThanEqual(vec4 x, vec4 y) bvec2 lessThanEqual(ivec2 x, ivec2 y) bvec3 lessThanEqual(ivec3 x, ivec3 y) bvec4 lessThanEqual(ivec4 x, ivec4 y)

Returns the component-wise compare of x <= y.

bvec2 greaterThan(vec2 x, vec2 y) bvec3 greaterThan(vec3 x, vec3 y) bvec4 greaterThan(vec4 x, vec4 y) bvec2 greaterThan(ivec2 x, ivec2 y) bvec3 greaterThan(ivec3 x, ivec3 y) bvec4 greaterThan(ivec4 x, ivec4 y)

Returns the component-wise compare of x > y.

bvec2 greaterThanEqual(vec2 x, vec2 y) bvec3 greaterThanEqual(vec3 x, vec3 y) bvec4 greaterThanEqual(vec4 x, vec4 y) bvec2 greaterThanEqual(ivec2 x, ivec2 y) bvec3 greaterThanEqual(ivec3 x, ivec3 y) bvec4 greaterThanEqual(ivec4 x, ivec4 y)

Returns the component-wise compare of x >= y.

bvec2 equal(vec2 x, vec2 y) bvec3 equal(vec3 x, vec3 y) bvec4 equal(vec4 x, vec4 y) bvec2 equal(ivec2 x, ivec2 y) bvec3 equal(ivec3 x, ivec3 y) bvec4 equal(ivec4 x, ivec4 y) bvec2 equal(bvec2 x, bvec2 y) bvec3 equal(bvec3 x, bvec3 y) bvec4 equal(bvec4 x, bvec4 y)

Returns the component-wise compare of x == y.

bvec2 notEqual(vec2 x, vec2 y) bvec3 notEqual(vec3 x, vec3 y) bvec4 notEqual(vec4 x, vec4 y) bvec2 notEqual(ivec2 x, ivec2 y) bvec3 notEqual(ivec3 x, ivec3 y) bvec4 notEqual(ivec4 x, ivec4 y) bvec2 notEqual(bvec2 x, bvec2 y) bvec3 notEqual(bvec3 x, bvec3 y) bvec4 notEqual(bvec4 x, bvec4 y)

Returns the component-wise compare of x != y.

bool any(bvec2 x) bool any(bvec3 x) bool any(bvec4 x)

Returns true if any component of x is true.

bool all(bvec2 x) bool all(bvec3 x) bool all(bvec4 x)

Returns true only if all components of x are true.

bvec2 not(bvec2 x bvec3 not(bvec3 x) bvec4 not(bvec4 x)

Returns the component-wise logical complement of x.

Texture Access Functions

Texture access functions are available to both vertex and fragment shaders. Each of these functions takes as its first argument a variable of type sampler. If a variable qualified by sampler1D is used, then the texture access operation reads from the 1D texture that has previously been associated with that sampler by the application. (It is an error for the application to associate a non-1D texture with a sampler1D variable.) Similarly, a sampler2D variable is used to access a 2D texture, and so on. The texture precedence rules for OpenGL fixed functionality are ignored. It is up to the application to set up texture state before the shader executes in order to get the expected results (see Section 7.9).

The texture access functions obtain texture values from either mipmapped or non-mipmapped textures. However, level-of-detail is not computed by fixed functionality for vertex shaders, so there are some differences in operation between vertex and fragment texture access functions. Texture properties such as size, pixel format, number of dimensions, filtering method, number of mipmap levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are taken into account as the texture is accessed through the built-in functions defined in this section.

In all functions that follow, the bias parameter is optional for fragment shaders. The bias parameter is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to the calculated level of detail before the texture access operation is performed. If the bias parameter is not provided, the implementation automatically selects level-of-detail. For a texture that is not mipmapped, the texture is used directly. If a mipmap texture is accessed from a fragment shader, the level-of-detail computed by the implementation is used during the texture lookup. If a mipmapped texture is accessed from a vertex shader, the base texture is used.

The built-in functions suffixed with “Lod” are allowed only in a vertex shader. For the “Lod” functions, lod is directly used as the level-of-detail. The built-in functions suffixed with “Proj” can perform projective texturing. This allows a texture to be projected onto an object in much the same way that a slide projector projects an image onto a surface. Functions suffixed with “Proj” can compute shadow maps for rendering shadows, among other things.

A number of examples in later sections illustrate the use of these functions. With the programmability available with the OpenGL Shading Language, texture memory can store much more than just image data. These texture access functions provide fast, flexible access to such data in order to achieve a wide variety of effects (see Table 5.7).

Table 5.7. Texture access functions

Syntax

Description

vec4 texture1D (sampler1D sampler, float coord [, float bias]) vec4 texture1DProj (sampler1D sampler, vec2 coord [, float bias]) vec4 texture1DProj (sampler1D sampler, vec4 coord [, float bias]) vec4 texture1DLod (sampler1D sampler, float coord, float lod) vec4 texture1DProjLod (sampler1D sampler, vec2 coord, float lod) vec4 texture1DProjLod (sampler1D sampler, vec4 coord, float lod)

Use the texture coordinate coord to access the 1D texture currently specified by sampler. For the projective (“Proj”) versions, the texture coordinate coord.s is divided by the last component of coord. The second and third components of coord are ignored for the vec4 coord variant.

vec4 texture2D (sampler2D sampler, vec2 coord [, float bias]) vec4 texture2DProj (sampler2D sampler, vec3 coord [, float bias]) vec4 texture2DProj (sampler2D sampler, vec4 coord [, float bias]) vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod) vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod) vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod)

Use the texture coordinate coord to access the 2D texture currently specified by sampler. For the projective (“Proj”) versions, the texture coordinate (coord.s, coord.t) is divided by the last component of coord. The third component of coord is ignored for the vec4 coord variant.

vec4 texture3D (sampler3D sampler, vec3 coord [, float bias]) vec4 texture3DProj (sampler3D sampler, vec4 coord [, float bias]) vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod) vec4 texture3DProjLod (sampler3D sampler, vec4 coord, float lod)

Use the texture coordinate coord to access the 3D texture currently specified by sampler. For the projective (“Proj”) versions, the texture coordinate is divided by coord.q.

vec4 textureCube (samplerCube sampler, vec3 coord [, float bias]) vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod)

Use the texture coordinate coord to access the cube map texture currently specified by sampler. The direction of coord selects the face in which to do a two-dimensional texture lookup.

vec4 shadow1D (sampler1DShadow sampler, vec3 coord [, float bias]) vec4 shadow2D (sampler2DShadow sampler, vec3 coord [, float bias]) vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord [, float bias]) vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord [, float bias]) vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod) vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod) vec4 shadow1DProjLod (sampler1DShadow sampler, vec4 coord, float lod) vec4 shadow2DProjLod (sampler2DShadow sampler, vec4 coord, float lod)

Use texture coordinate coord to do a depth comparison lookup on the depth texture specified by sampler. The third component of coord (coord.p) is compared to the value read from the depth texture. The texture bound to sampler must be a depth texture or results are undefined. For the projective (“Proj”) version of each built-in, the texture coordinate is divided by coord.q, giving a depth value of coord.p/coord.q. The second component of coord is ignored for the “1D” variants.

Texturing results are undefined if

  • A texture function other than one of the shadow variants is called with a sampler whose texture is a depth texture with depth comparisons enabled,

  • A shadow texture call is made to a sampler whose texture is a depth texture with depth comparisons disabled, or

  • A shadow texture call is made to a sampler whose texture is not a depth texture.

Fragment Processing Functions

Fragment processing functions are only available in shaders intended for use on the fragment processor. This category has three built-in functions. Two obtain derivatives and the other estimates the filter width used to antialias procedural textures.

The derivative functions, dFdx and dFdy, determine the rate of change of an expression. The function dFdx(p) evaluates the derivative of the expression p in the x direction in window coordinates, and the function dFdy(p) evaluates the derivative of the expression p in the y direction in window coordinates. These values indicate how fast the expression is changing in window space, and this information can be used to take steps to prevent aliasing. For instance, if texture coordinates are changing rapidly, it may be better to set the resulting color to the average color for the texture in order to avoid aliasing.

It only makes sense to apply these functions to expressions that vary from one fragment to the next. Because the value of a uniform variable does not change from one pixel to the next, its derivative in x and in y is always 0. See Table 5.8.

Table 5.8. Fragment Processing Functions

Syntax

Description

float dFdx (float p) vec2 dFdx (vec2 p) vec3 dFdx (vec3 p) vec4 dFdx (vec4 p)

Returns the derivative in x for the input argument p.

float dFdy (float p) vec2 dFdy (vec2 p) vec3 dFdy (vec3 p) vec4 dFdy (vec4 p)

Returns the derivative in y for the input argument p.

float fwidth (float p) vec2 fwidth (vec2 p) vec3 fwidth (vec3 p) vec4 fwidth (vec4 p)

Returns the sum of the absolute derivative in x and y for the input argument p, i.e., return = abs (dFdx (p)) + abs (dFdy (p));

Noise Functions

Noise functions (see Table 5.9) are available to both fragment and vertex shaders. These stochastic functions, first described by Ken Perlin, increase visual complexity. Values returned by the following noise functions give the appearance of randomness, but they are not truly random. A more complete description of and motivation for the noise function can be found in Chapter 15.

Table 5.9. Noise Functions

Syntax

Description

float noise1 (float x) float noise1 (vec2 x) float noise1 (vec3 x) float noise1 (vec4 x)

Returns a 1D noise value based on the input value x.

vec2 noise2 (float x) vec2 noise2 (vec2 x) vec2 noise2 (vec3 x) vec2 noise2 (vec4 x)

Returns a 2D noise value based on the input value x.

vec3 noise3 (float x) vec3 noise3 (vec2 x) vec3 noise3 (vec3 x) vec3 noise3 (vec4 x)

Returns a 3D noise value based on the input value x.

vec4 noise4 (float x) vec4 noise4 (vec2 x) vec4 noise4 (vec3 x) vec4 noise4 (vec4 x)

Returns a 4D noise value based on the input value x.

The built-in noise functions are defined to have the following characteristics:

  • The return values are always in the range [–1,1] and cover at least the range [–0.6,0.6] with a Gaussian-like distribution.

  • The return values have an overall average of 0.

  • The functions are repeatable, in that a particular input value always produces the same return value.

  • They are statistically invariant under rotation; that is, no matter how the domain is rotated, it has the same statistical character.

  • They have a statistical invariance under translation; that is, no matter how the domain is translated, it has the same statistical character.

  • They typically give different results under translation.

  • The spatial frequency is narrowly concentrated, centered somewhere between 0.5 and 1.0.

  • They are C1 continuous everywhere; that is the first derivative is continuous.

Summary

The OpenGL Shading Language contains a rich set of built-in functions. Some of these functions are similar to those found in C and C++, and others are similar to those found in RenderMan. These functions expose hardware functionality (e.g., texture access) or support common operations (e.g., square root, clamp), or they represent operations likely to be accelerated in future generations of graphics hardware (trigonometry functions, noise, etc.).

Function overloading is used extensively because many of these functions operate on either vectors or scalars. Vendors that support the OpenGL Shading Language are expected to provide optimal implementations of these functions, so the built-in functions should be used whenever possible.

The built-in mathematical functions can be used in some unique and perhaps unexpected ways to create procedural textures. Shader examples throughout the rest of this book illustrate this. Visualizing the function needed to achieve a particular effect can be a vital part of the shader development process.

Further Information

Many of the built-in functions described in this chapter are used in example shaders in the remainder of this book. All you need to do is keep reading to see them in action.

Some additional detail on the built-in functions can be found in the The OpenGL Shading Language, Version 1.10, by John Kessenich, Dave Baldwin, and Randi Rost (2004).

Various OpenGL Shading Language built-in functions, including the derivative and filter width functions, were inspired by similar functions in RenderMan. Motivation for some of these functions is discussed in The RenderMan Companion: A Programmer’s Guide to Realistic Computer Graphics by Steve Upstill (1990) and Advanced RenderMan: Creating CGI for Motion Pictures by Tony Apodaca and Larry Gritz (1999). For additional details on noise functions, see the papers by Perlin and the references provided at the end of Chapter 15.

  1. Apodaca, Anthony A., and Larry Gritz, Advanced RenderMan: Creating CGI for Motion Pictures, Morgan Kaufmann Publishers, San Francisco, 1999. http://www.renderman.org/RMR/Books/arman/materials.html

  2. Kessenich, John, Dave Baldwin, and Randi Rost, The OpenGL Shading Language, Version 1.10, 3Dlabs, April 2004. http://www.opengl.org/documentation/spec.html

  3. Perlin, Ken, An Image Synthesizer, Computer Graphics (SIGGRAPH ’85 Proceedings), pp. 287–296, July 1985.

  4. Perlin, Ken, Improving Noise, Computer Graphics (SIGGRAPH 2002 Proceedings), pp. 681–682, July 2002. http://mrl.nyu.edu/perlin/paper445.pdf

  5. Pixar, The RenderMan Interface Specification, Version 3.2, Pixar, July 2000. https://renderman.pixar.com/products/rispec/index.htm

  6. Segal, Mark, and Kurt Akeley, The OpenGL Graphics System: A Specification (Version 2.0), Editor (v1.1): Chris Frazier, (v1.2–1.5): Jon Leech, (v2.0): Jon Leech and Pat Brown, Sept. 2004. http://www.opengl.org/documentation/spec.html

  7. Upstill, Steve, The RenderMan Companion: A Programmer’s Guide to Realistic Computer Graphics, Addison-Wesley, Reading, Massachusetts, 1990.

  8. Zwillinger, Dan, CRC Standard Mathematical Tables and Formulas, 30th Edition, CRC Press, 1995. http://www.geom.uiuc.edu/docs/reference/CRC-formulas/

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
44.210.151.5