Chapter 21. High-Level Shading: The Real Slim Shader

by Benjamin Lipchak

WHAT YOU'LL LEARN IN THIS CHAPTER:

How To

Functions You'll Use

Create shader/program objects

glCreateShaderObjectARB/glCreateProgramObjectARB

Specify shaders and compile

glShaderSourceARB/glCompileShaderARB

Attach/detach shaders and link

glAttachObjectARB/glDetachObjectARB/glLinkProgramARB

Switch between programs

glUseProgramObjectARB

Specify a uniform

glUniform*ARB

Get error and warning information

glGetInfoLogARB

You could, in theory, write all your applications in assembly language. But you don't, and there are good reasons for not doing so: development time efficiency, readability, maintainability, and portability, to name just a few. The benefits of assembly are becoming scarce with today's high-level language compilers generating code that performs as well as, or even outperforms, hand-written assembly.

So then why did we bother discussing low-level shading in the preceding chapters instead of skipping straight to high-level shaders, based on the OpenGL Shading Language (GLSL)? The answer is based on availability. The ARB-standardized low-level shader extensions, covered in Chapter 20, “Low-Level Shading: Coding to the Metal,” have been available for years and have been the only game in town. Though in development for years, no high-level alternative was available on OpenGL until recently. So game and application developers who wanted to incorporate shading capabilities embraced the low-level extensions as their only choice at the time.

The adoption of low-level extensions was relatively rapid because these extensions exposed functionality not previously available. It is likely that the migration to GLSL will be slower because high-level shaders, for the most part, expose only equivalent functionality, just in an easier-to-use way. Low-level shaders, on the other hand, are entrenched with a two-year headstart. Applications with long development cycles may take the “if it ain't broke, don't fix it” mentality, keeping low-level shaders alive and kicking for years to come. But in the long run, GLSL will be the tool of choice, and low-level shaders will be a footnote in OpenGL history.

Managing High-Level Shaders

The GLSL ARB extensions are quite a departure from the core OpenGL API and other extensions in terms of the API they introduce. No more of the Gen/Bind/Delete that you're used to; GLSL gets all new entrypoints.

Shader Objects

GLSL uses two types of objects: shader objects and program objects. The first objects we will look at, shader objects, are loaded with shader text and compiled.

Creating and Deleting

You create shader objects by calling glCreateShaderObjectARB and passing it the type of shader you want, either vertex or fragment. This function returns a handle to the shader object used to reference it in subsequent calls:

GLhandleARB myVertexShader   = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
GLhandleARB myFragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

Beware that object creation may fail, in which case 0 (zero) will be returned. This may happen if OpenGL runs out of memory resources or object handles. When you're done with your shader objects, you should clean up after yourself:

glDeleteObjectARB(myVertexShader);
glDeleteObjectARB(myFragmentShader);

Some other OpenGL objects, including texture objects, unbind an object during deletion if it's currently in use. GLSL objects are different. glDeleteObjectARB simply marks the object for future deletion, which will occur as soon as the object is no longer being used.

Specifying Shader Text

A shader object's goal is simply to accept shader text and compile it. Your shader text can be hard-coded as a string-literal, read from a file on disk, or generated on the fly. One way or another, it needs to be in a string so you can load it into your shader object:

GLcharARB *myStringPtrs[1];
myStringPtrs[0] = vertexShaderText;
glShaderSourceARB(myVertexShader, 1, myStringPtrs, NULL);
myStringPtrs[0] = fragmentShaderText;
glShaderSourceARB(myFragmentShader, 1, myStringPtrs, NULL);

glShaderSourceARB is set up to accept multiple individual strings. The second argument is a count that indicates how many string pointers to look for. The strings are strung together into a single long string before being compiled. This capability can be useful if you're loading reusable subroutines from a library of functions:

GLcharARB *myStringPtrs[3];
myStringPtrs[0] = vsMainText;
myStringPtrs[1] = myNoiseFuncText;
myStringPtrs[2] = myBlendFuncText;
glShaderSourceARB(myVertexShader, 3, myStringPtrs, NULL);

If all your strings are null-terminated, you don't need to specify string lengths in the fourth argument and can pass in NULL instead. But for shader text that is not null- terminated, you need to provide the length; lengths do not include the null terminator if present. You can use –1 for strings that are null-terminated. The following code passes in a pointer to an array of lengths along with the array of string pointers:

GLint fsLength = strlen(fragmentShaderText);
myStringPtrs[0] = fragmentShaderText;
glShaderSourceARB(myFragmentShader, 1, myStringPtrs, &fsLength);

Compiling Shaders

After your shader text is loaded into a shader object, you need to compile it. Compiling parses your shader and makes sure there are no errors:

glCompileShaderARB(myVertexShader);
glCompileShaderARB(myFragmentShader);

You can query a flag in each shader object to see whether the compile was successful. Each shader object also has an information log that contains error messages if the compilation failed. It might also contain warnings or other useful information even if your compilation was successful. These logs are primarily intended for use as a tool while you are developing your GLSL application:

glCompileShaderARB(myVertexShader);
glGetObjectParameterivARB(myVertexShader, GL_OBJECT_COMPILE_STATUS_ARB,
                          &success);
if (!success)
{
    GLbyte infoLog[MAX_INFO_LOG_SIZE];
    glGetInfoLogARB(myVertexShader, MAX_INFO_LOG_SIZE, NULL, infoLog);
    fprintf(stderr, "Error in vertex shader compilation!
");
    fprintf(stderr, "Info log: %s
", infoLog);
    Sleep(10000);
    exit(0);
}

The returned info log string is always null terminated. If you don't want to allocate a large static array to store the info log, you can find out the exact size of the info log before querying it:

glGetObjectParameterivARB(myVertexShader, GL_OBJECT_INFO_LOG_LENGTH_ARB,
               &infoLogSize);

Program Objects

The second type of object GLSL uses is a program object. This object acts as a container for shader objects, linking them together into a single executable. You can specify a GLSL shader for each replaceable section of the conventional OpenGL pipeline. Currently, only vertex and fragment stages are replaceable, but that list could be extended in the future to include additional stages.

Creating and Deleting

Program objects are created and deleted the same way as shader objects. The difference is that there's only one kind of program object, so its creation entrypoint doesn't take an argument:

GLhandleARB myProgram = glCreateProgramObjectARB();
...
glDeleteObjectARB(myProgram);

Attaching and Detaching

A program object is a container. You need to attach your shader objects to it if you want GLSL instead of fixed functionality:

glAttachObjectARB(myProgram, myVertexShader);
glAttachObjectARB(myProgram, myFragmentShader);

You can even attach multiple shader objects of the same type to your program object. Similar to loading multiple shader source strings into a single shader object, this makes it possible to include function libraries shared by more than one of your program objects.

You can choose to replace only part of the pipeline with GLSL and leave the rest to fixed functionality. Just don't attach shaders for the parts you want to leave alone. Or if you're switching between GLSL and fixed functionality for part of the pipeline, you can detach a previously attached shader object. You can even detach both shaders, in which case you're back to full fixed functionality:

glDetachObjectARB(myProgram, myVertexShader);
glDetachObjectARB(myProgram, myFragmentShader);

Linking Programs

Before you can use GLSL for rendering, you have to link your program object. This process takes each of the previously compiled shader objects and links them into a single executable:

glLinkProgramARB(myProgram);

You can query a flag in the program object to see whether the link was successful. The object also has an information log that contains error messages if the link failed. The log might also contain warnings or other useful information even if your link was successful:

glLinkProgramARB(myProgram);
glGetObjectParameterivARB(myProgram, GL_OBJECT_LINK_STATUS_ARB, &success);
if (!success)
{
    GLbyte infoLog[MAX_INFO_LOG_SIZE];
    glGetInfoLogARB(myProgram, MAX_INFO_LOG_SIZE, NULL, infoLog);
    fprintf(stderr, "Error in program linkage!
");
    fprintf(stderr, "Info log: %s
", infoLog);
    Sleep(10000);
    exit(0);
}

Validating Programs

If your link was successful, odds are good that your shaders will be executable when it comes time to render. But some things aren't known at link time, such as the values assigned to texture samplers, described in subsequent sections. A sampler may be set to an invalid value, or multiple samplers of different types may be illegally set to the same value. At link time, you don't know what the state is going to be when you render, so errors cannot be thrown at that time. When you validate, however, it looks at the current state so you can find out once and for all whether your GLSL shaders are going to execute when you draw that first triangle:

glValidateProgramARB(myProgram);
glGetObjectParameterivARB(myProgram, GL_OBJECT_VALIDATE_STATUS_ARB, &success);
if (!success)
{
    GLbyte infoLog[MAX_INFO_LOG_SIZE];
    glGetInfoLogARB(myProgram, MAX_INFO_LOG_SIZE, NULL, infoLog);
    fprintf(stderr, "Error in program validation!
");
    fprintf(stderr, "Info log: %s
", infoLog);
    Sleep(10000);
    exit(0);
}

Again, if the validation fails, an explanation and possibly tips for avoiding the failure are included in the program object's info log. Note that validating your program object before rendering with it is not a requirement, but if you do try to use a program object that would have failed validation, your rendering commands will fail and throw OpenGL errors.

Using Programs

Finally, you're ready to turn on your program. Unlike other OpenGL features, GLSL mode is not toggled with glEnable/glDisable:

glUseProgramObject(myProgram);

You can use this function to enable GLSL with a particular program object and also to switch between different program objects. To disable GLSL and switch back to fixed functionality, you also use this function, passing in 0:

glUseProgramObject(0);

You can query for the current program object handle at any time:

currentProgObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);

Now that you know how to manage your shaders, you can focus on their contents. The syntax of GLSL is largely the same as that of C/C++, so you should be able to dive right in.

Setting Up the Extensions

Like low-level shader extensions, GLSL is not yet part of core OpenGL at the time of this book's printing. Therefore, the presence of the desired extensions must be queried, and entrypoint function pointers must also be obtained, as in Listing 21.1.

You must check four GLSL extensions: GL_ARB_shader_objects, GL_ARB_vertex_shader, GL_ARB_fragment_shader, and GL_ARB_shading_language_100. The first contains the shared functionality between vertex and fragment shaders. The last reflects the version of the OpenGL Shading Language available. Updated versions will likely be made available over time.

Example 21.1. Checking for the Presence of OpenGL Features

// Make sure required functionality is available!
if (!gltIsExtSupported("GL_ARB_vertex_shader") || 
    !gltIsExtSupported("GL_ARB_fragment_shader") ||
    !gltIsExtSupported("GL_ARB_shader_objects") ||
    !gltIsExtSupported("GL_ARB_shading_language_100"))
{
    fprintf(stderr, "GLSL extensions not available!
");
    Sleep(2000);
    exit(0);
}

glCreateShaderObjectARB = gltGetExtensionPointer("glCreateShaderObjectARB");
glCreateProgramObjectARB = gltGetExtensionPointer("glCreateProgramObjectARB");
glAttachObjectARB = gltGetExtensionPointer("glAttachObjectARB");
glDetachObjectARB = gltGetExtensionPointer("glDetachObjectARB");
glDeleteObjectARB = gltGetExtensionPointer("glDeleteObjectARB");
glShaderSourceARB = gltGetExtensionPointer("glShaderSourceARB");
glCompileShaderARB = gltGetExtensionPointer("glCompileShaderARB");
glLinkProgramARB = gltGetExtensionPointer("glLinkProgramARB");
glValidateProgramARB = gltGetExtensionPointer("glValidateProgramARB");
glUseProgramObjectARB = gltGetExtensionPointer("glUseProgramObjectARB");
glGetObjectParameterivARB = gltGetExtensionPointer("glGetObjectParameterivARB");
glGetInfoLogARB = gltGetExtensionPointer("glGetInfoLogARB");
glUniform1fARB = gltGetExtensionPointer("glUniform1fARB");
glGetUniformLocationARB = gltGetExtensionPointer("glGetUniformLocationARB");

if (!glCreateShaderObjectARB || !glCreateProgramObjectARB || 
    !glAttachObjectARB || !glDetachObjectARB || !glDeleteObjectARB || 
    !glShaderSourceARB || !glCompileShaderARB || !glLinkProgramARB ||
    !glValidateProgramARB || !glUseProgramObjectARB || 
    !glGetObjectParameterivARB || !glGetInfoLogARB || 
    !glUniform1fARB || !glGetUniformLocationARB)
{
    fprintf(stderr, "Not all entrypoints were available!
");
    Sleep(2000);
    exit(0);
}

Variables

Variables and functions must be declared in advance. Your variable name can use any letters (case-sensitive), numbers, or an underscore, but it can't begin with a number. Also, your variable cannot begin with the prefix gl_, which is reserved for built-in variables and functions. A list of reserved keywords available in the OpenGL Shading Language specification is also off-limits.

Basic Types

In addition to the Boolean, integer, and floating-point types found in C, GLSL introduces some data types commonly used in shaders. Table 21.1 lists these basic data types.

Table 21.1. Basic Data Types

Type

Description

void

A data type required for functions that don't return a value. Functions that take no arguments can optionally use void as well.

bool

A Boolean variable used primarily for conditionals and loops. It can be assigned to keywords true and false, or any expression that evaluates to a Boolean.

Int

A variable represented by a signed integer with at least 16 bits. It can be expressed in decimal, octal, or hexadecimal. It is primarily used for loop counters and array indexing.

float

A floating-point variable approximating IEEE single-precision. It can be expressed in scientific notation (for example, 0.0001 = 1e-4).

bvec2

A two-component Boolean vector.

bvec3

A three-component Boolean vector.

bvec4

A four-component Boolean vector.

ivec2

A two-component integer vector.

ivec3

A three-component integer vector.

ivec4

A four-component integer vector.

Vec2

A two-component floating-point vector.

Vec3

A three-component floating-point vector.

Vec4

A four-component floating-point vector.

Mat2

A 2×2 floating-point matrix. Matrices are accessed in column-major order.

Mat3

A 3×3 floating-point matrix.

Mat4

A 4×4 floating-point matrix.

sampler1D

A special-purpose constant used by built-in texture functions to reference a specific 1D texture. It can be declared only as a uniform or function argument.

sampler2D

A constant used for referencing a 2D texture.

sampler3D

A constant used for referencing a 3D texture.

samplerCube

A constant used for referencing a cube map texture.

sampler1DShadow

A constant used for referencing a 1D depth texture with shadow comparison.

sampler2DShadow

A constant used for referencing a 2D depth texture with shadow comparison.

Structures

Structures can be used to group basic data types into a user-defined data type. When defining the structure, you can declare instances of the structure at the same time, or you can declare them later:

struct surface {
    float indexOfRefraction;
    float reflectivity;
    vec3 color;
    float turbulence;
} myFirstSurf;

surface mySecondSurf;

You can assign one structure to another (=) or compare two structures (==, !=). For both of these operations, the structures must be of the same declared type. Two structures are considered equal if each of their member fields is component-wise equal. To access a single field of a structure, you use the selector (.):

vec3 totalColor = myFirstSurf.color + mySecondSurf.color;

Structure definitions must contain at least one member. Arrays, discussed next, may be included in structures, but only when a specific array size is provided. Unlike C language structures, GLSL does not allow bit fields. Structures within structures are allowed as long as the member structure is declared in advance or in place, not later in the shader:

struct superSurface {
    vec3 points[30];    // Sized arrays are okay
    surface surf;       // Okay, as surface was defined earlier
    struct velocity {   // Okay, velocity struct defined in place
        float speed;
        vec3 direction;
    } velo;
    subSurface sub;     // ILLEGAL!!  Forward declaration
};

struct subSurface {
    int id;
};

Arrays

One-dimensional arrays of any type (including structures) can be declared. You don't need to declare the size of the array as long as it is always indexed with a constant integer expression. Otherwise, you must declare its size up front:

vec4 lightPositions[8];
surface mySurfaces[];
const int numSurfaces = 5;
surface myFiveSurfaces[numSurfaces];

You also must declare an explicit size for your array when the array is declared as a parameter in a function declaration or as a member of a structure.

Qualifiers

Variables can be declared with an optional type qualifier. Table 21.2 lists the available qualifiers.

Table 21.2. Type Qualifiers

Qualifier

Description

const

Constant value initialized during declaration. It is read-only during shader execution. It is also used with a function call argument to indicate it's a constant that can't be written within the function.

attribute

Read-only per-vertex data, available only within vertex shaders. This data comes from current vertex state or from vertex arrays. It must be declared globally (outside all functions).

uniform

Another value that remains constant during each shader execution, but unlike a const, a uniform's value is not known at compile time and is initialized outside the shader. A uniform is shared by the currently active vertex and fragment shaders and must be declared globally.

varying

Outputs of the vertex shader, such as colors or texture coordinates, that correspond to read-only interpolated inputs of the fragment shader. They must be declared globally.

in

A qualifier used with a function call argument to indicate it's only an input, and any changes to the variable within the called function shouldn't affect the value in the calling function. This is the default behavior for function arguments if no qualifier is present.

out

A qualifier used with a function call argument to indicate it's only an output, so no value needs to be actually passed into the function.

inout

A qualifier used with a function call argument to indicate it's both an input and an output. A value is passed in from the calling function, and that value is replaced by the called function.

Built-in Variables

Built-in variables allow interaction with fixed functionality. They don't need to be declared before use. Tables 21.3 and 21.4 list most of the built-in variables. Refer to the GLSL specification for built-in uniforms and constants.

Table 21.3. Built-in Vertex Shader Variables

Name

Type

Description

gl_Position

vec4

Output for transformed vertex position that will be used by fixed functionality primitive assembly, clipping, and culling; all vertex shaders must write to this variable.

gl_PointSize

float

Output for the size of the point to be rasterized, measured in pixels.

gl_ClipVertex

vec4

Output for the coordinate to use for user clip-plane clipping.

gl_Color

vec4

Input attribute corresponding to per-vertex primary color.

gl_SecondaryColor

vec4

Input attribute corresponding to per-vertex secondary color.

gl_Normal

vec3

Input attribute corresponding to per-vertex normal.

gl_Vertex

vec4

Input attribute corresponding to object-space vertex position.

gl_MultiTexCoordn

vec4

Input attribute corresponding to per-vertex texture coordinate n.

gl_FogCoord

float

Input attribute corresponding to per-vertex fog coordinate.

gl_FrontColor

vec4

Varying output for front primary color.

gl_BackColor

vec4

Varying output for back primary color.

gl_FrontSecondaryColor

vec4

Varying output for front secondary color.

gl_BackSecondaryColor

vec4

Varying output for back secondary color.

gl_TexCoord[]

vec4

Array of varying outputs for texture coordinates.

gl_FogFragCoord

float

Varying output for the fog coordinate.

Table 21.4. Built-in Fragment Shader Variables

Name

Type

Description

gl_FragCoord

vec4

Read-only input containing the window-space x, y, z, and 1/w.

gl_FrontFacing

bool

Read-only input whose value is true if part of a front-facing primitive.

gl_FragColor

vec4

Output for the color to use for subsequent per-pixel operations.

gl_FragDepth

float

Output for the depth to use for subsequent per-pixel operations; if unwritten, the fixed functionality depth is used instead.

gl_Color

vec4

Interpolated read-only input containing the primary color.

gl_SecondaryColor

vec4

Interpolated read-only input containing the secondary color.

gl_TexCoord[]

vec4

Array of interpolated read-only inputs containing texture coordinates.

gl_FogFragCoord

float

Interpolated read-only input containing the fog coordinate.

Expressions

The following sections describe various operators and expressions found in GLSL.

Operators

All the familiar C operators are available in GLSL with few exceptions. See Table 21.5 for a complete list.

Table 21.5. Operators in Order of Precedence (From Highest to Lowest)

Operator

Description

()

Parenthetical grouping, function call or constructor

[]

Array subscript, vector or matrix selector

.

Structure field selector, vector component selector

++ --

Prefix or post-fix increment and decrement

+ - !

Unary addition, subtraction, logical NOT

* /

Multiplication and division

+ -

Binary addition and subtraction

< > <= >= == !=

Less than, greater than, less than or equal to, greater than or equal to, equal to, not equal to

&& || ^^

Logical AND, OR, XOR

?:

Conditional

= += -= *= /=

Assignment, arithmetic assignments

,

Sequence

A few operators are missing from GLSL. Because there are no pointers to worry about, you don't need an address-of operator (&) or a dereference operator (*). A typecast operator is not needed because typecasting is not allowed. Bit-wise operators (&, |, ^, ~, <<, >>, &=, |=, ^=, <<=, >>=) are reserved for future use, as are modulus operators (%, %=).

Array Access

Arrays are indexed using integer expressions, with the first array element at index 0. Shader execution is undefined if an attempt is made to access an array with an index less than zero or greater than or equal to the size of the array:

vec4 myFifthColor, ambient, diffuse[6], specular[6];
...
myFifthColor = ambient + diffuse[5] + specular[5];

//Here's how NOT to index an array!
vec4 mySyntaxError=ambient + diffuse[-1] + specular[6];

Constructors

Constructors are special functions primarily used to initialize variables, especially of multicomponent data types, but not arrays. They take the form of a function call with the name of the function being the same as the name of the type:

vec3 myNormal = vec3(0.0, 1.0, 0.0);

Constructors are not limited to declaration initializers; they can be used as expressions anywhere in your shader:

greenTint = myColor + vec3(0.0, 1.0, 0.0);

A single scalar value is assigned to all elements of a vector:

ivec4 myColor = ivec4(255);  // all 4 components get 255

You can mix and match scalars, vectors, and matrices in your constructor, as long as you end up with enough components to initialize the entire data type. Any extra components are dropped:

vec4 myVector1 = vec4(x, vec2(y, z), w);
vec2 myVector2 = vec2(myVector1);       // z, w are dropped
float myFloat = float(myVector2);       // y dropped

Matrices are constructed in column-major order. If you provide a single scalar value, that value is used for the diagonal matrix elements, and all other elements are set to 0:

// all of these are same 2x2 identity matrix
mat2 myMatrix1 = mat2(1.0, 0.0, 0.0, 1.0);
mat2 myMatrix2 = mat2(vec2(1.0, 0.0), vec2(0.0, 1.0));
mat2 myMatrix3 = mat2(1.0);

You can also use constructors to convert between the different scalar types. This is the only way to perform type conversions. No implicit or explicit type casts or promotions are possible.

The conversion from int to float is obvious. When you are converting from float to int, the fractional part is dropped. When you are converting from int or float to bool, values of 0 or 0.0 are converted to false, and anything else is converted to true. When you are converting from bool to int or float, true is converted to 1 or 1.0, and false is converted to 0 or 0.0:

float myFloat = 4.7;
int myInt = int(myFloat);  // myInt = 4
bool myBool = bool(myInt); // myBool = true
myFloat = float(myBool);  // myFloat = 1

Finally, you can initialize structures by providing arguments in the same order and of the same type as the structure definition:

struct surface {
    float indexOfRefraction;
    float reflectivity;
    vec3 color;
    float turbulence;
};

surface mySurf = surface(ior, refl, vec3(red, green, blue), turb);

Component Selectors

Individual components of a vector can be accessed by using dot notation along with {x,y,z,w}, {r,g,b,a}, or {s,t,p,q}. These different notations are useful for positions and normals, colors, and texture coordinates, respectively. Notice the p in place of the usual r texture coordinate. This component has been renamed to avoid ambiguity with the r color component. You cannot mix and match selectors from the different notations:

vec3 myVector = {0.25, 0.5, 0.75};
float myR = myVector.r;   // 0.25
vec2 myYZ = myVector.yz;  // 0.5, 0.75
float myQ = myVector.q;   // not allowed, accesses component beyond vec3
float myRY = myVector.ry; // not allowed, mixes two notations

You can use the component selectors to rearrange the order of components or replicate them:

vec3 myZYX = myVector.zyx;   // reverse order
vec4 mySSTT = myVector.sstt; // replicate s and t twice each

You can also use them as writemasks on the left side of an assignment to select which components are modified. In this case, you cannot use component selectors more than once:

vec4 myColor = vec4(0.0, 1.0, 2.0, 3.0);
myColor.x = -1.0;               // -1.0, 1.0, 2.0, 3.0
myColor.yz = vec2(-2.0, -3.0);  // -1.0, -2.0, -3.0, 3.0
myColor.wx = vec2(0.0, 1.0);    // 1.0, -2.0, -3.0, 0.0
myColor.zz = vec2(2.0, 3.0);    // not allowed

Another way to get at individual vector components or matrix components is to use array subscript notation. This way, you can use an arbitrarily computed integer index to access your vector or matrix as if it were an array. Shader execution is undefined if an attempt is made to access a component outside the bounds of the vector or matrix:

float myY = myVector[1];
float myBug = myVector[-1]; // Don't try this!

For matrices, providing a single array index accesses the corresponding matrix column as a vector. Providing a second array index accesses the corresponding vector component:

mat3 myMatrix = mat3(1.0);
vec3 myFirstColumn = myMatrix[0]; // first column: 1.0, 0.0, 0.0
float element21 = myMatrix[2][1]; // last column, middle row: 0.0

Control Flow

Low-level shaders allow only a single stream of linear execution. GLSL introduces a variety of familiar nonlinear flow mechanisms that reduce code size, make more complex algorithms possible, and make shaders more readable.

Loops

For, while, and do/while loops are all supported with the same syntax as in C/C++. Loops can be nested. You can use continue and break to prematurely move on to the next iteration or break out of the loop:

for (l = 0; l < numLights; l++)
{
    if (!lightExists[l])
        continue;
    color += light[l];
}

while (true)
{
    if (lightNum < 0)
       break;
    color += light[lightNum];
    lightNum--;
}

do
{
    color += light[lightNum];
    lightNum--;
} while (lightNum > 0);

if/else

You can use if and if/else clauses to select between multiple blocks of code. These conditionals can also be nested:

color = unlitColor;
if (numLights > 0)
{
    color = litColor;
}

if (numLights > 0)
{
    color = litColor;
}
else
{
    color = unlitColor;
}

discard

Fragment shaders have a special control flow mechanism called discard. It terminates execution of the current fragment's shader. All subsequent per-fragment pipeline stages are skipped, and the fragment is not written to the framebuffer:

// e.g. perform an alpha test within your fragment shader
if (color.a < 0.9)
    discard;

Functions

Functions are used to modularize shader code. All shaders must define a main function, which is the place where execution begins. The void parameter list here is optional, but not the void return:

void main(void)
{
    ...
}

Functions must be either defined or declared with a prototype before use. These definitions or declarations should occur globally, outside any function. Return types are required, as are types for each function argument. Also, arguments can have an optional qualifier in, out, inout, or const (see Table 21.2):

// function declaration
bool isAnyComponentNegative(const vec4 v);

// function definition
bool isAnyComponentNegative(const vec4 v)
{
    if ((v.x < 0.0) || (v.y < 0.0) ||
        (v.z < 0.0) || (v.w < 0.0))
        return true;
    else
        return false;
}

// function use
void main()
{
    bool someNeg = isAnyComponentNegative(gl_MultiTexCoord0);
    ...
}

Structures are allowed as arguments and return types. Arrays are allowed only as arguments, in which case the declaration and definition would include the array name with size, whereas the function call would just use the array name without brackets or size:

vec4 sumMyVectors(int howManyToSum, vec4 v[10]);

void main()
{
    vec4 myColors[10];
    ...
    gl_FragColor = sumMyVectors(6, myColors);
}

You can give more than one function the same name, as long as the return type or argument types are different. This is called function name overloading and is useful if you want to perform the same type of operation on, for example, different sized vectors:

float multiplyAccumulate(float a, float b, float c)
{
    return (a * b) + c;  // scalar definition
}

vec4 multiplyAccumulate(vec4 a, vec4 b, vec4 c)
{
    return (a * b) + c;  // 4-vector definition
}

Recursive functions are not allowed. In other words, the same function cannot be present more than once in the current call stack. Some compilers may be able to catch this and throw an error, but in any case, shader execution will be undefined.

Approximately 50 built-in functions provide all sorts of useful calculations, ranging from simple arithmetic to trigonometry. You can consult the GLSL specification for the complete list and descriptions.

Texture Lookup Functions

Texture lookup built-in functions deserve special mention. Whereas some of the other built-in functions are provided as a convenience because you could code your own versions relatively easily, texture lookup built-in functions, listed in Table 21.6, are crucial to perform even the most basic texturing.

Table 21.6. Texture Lookup Built-in Functions

Prototype

vec4 texture1D(sampler1D sampler, float coord [,
Texture Lookup Built-in Functions float bias] )
vec4 texture1DProj(sampler1D sampler, vec2 coord [
Texture Lookup Built-in Functions, float bias] )
vec4 texture1DProj(sampler1D sampler, vec4 coord [
Texture Lookup Built-in Functions, float bias] )
vec4 texture1DLod(sampler1D sampler, float coord,
Texture Lookup Built-in Functions float lod)
vec4 texture1DProjLod(sampler1D sampler, vec2
Texture Lookup Built-in Functions coord, float lod)
vec4 texture1DProjLod(sampler1D sampler, vec4
Texture Lookup Built-in Functions coord, float lod)
vec4 texture2D(sampler2D sampler, vec2 coord [,
Texture Lookup Built-in Functions float bias] )
vec4 texture2DProj(sampler2D sampler, vec3 coord [
Texture Lookup Built-in Functions, float bias] )
vec4 texture2DProj(sampler2D sampler, vec4 coord [
Texture Lookup Built-in Functions, float bias] )
vec4 texture2DLod(sampler2D sampler, vec2 coord,
Texture Lookup Built-in Functions float lod)
vec4 texture2DProjLod(sampler2D sampler, vec3
Texture Lookup Built-in Functions coord, float lod)
vec4 texture2DProjLod(sampler2D sampler, vec4
Texture Lookup Built-in Functions coord, float lod)
vec4 texture3D(sampler3D sampler, vec3 coord [,
Texture Lookup Built-in Functions float bias] )
vec4 texture3DProj(sampler3D sampler, vec4 coord [
Texture Lookup Built-in Functions, float bias] )
vec4 texture3DLod(sampler3D sampler, vec3 coord,
Texture Lookup Built-in Functions float lod)
vec4 texture3DProjLod(sampler3D sampler, vec4
Texture Lookup Built-in Functions coord, float lod)
vec4 textureCube(samplerCube sampler, vec3 coord [
Texture Lookup Built-in Functions, float bias] )
vec4 textureCubeLod(samplerCube sampler, vec3
Texture Lookup Built-in Functions coord, float lod)
vec4 shadow1D(sampler1DShadow sampler, vec3 coord
Texture Lookup Built-in Functions [, float bias] )
vec4 shadow2D(sampler2DShadow sampler, vec3 coord
Texture Lookup Built-in Functions [, float bias] )
vec4 shadow1DProj(sampler1DShadow sampler, vec4
Texture Lookup Built-in Functions coord, [, float bias] )
vec4 shadow2DProj(sampler2DShadow sampler, vec4
Texture Lookup Built-in Functions coord, [, float bias] )
vec4 shadow1DLod(sampler1DShadow sampler, vec3
Texture Lookup Built-in Functions coord, float lod)
vec4 shadow2DLod(sampler2DShadow sampler, vec3
Texture Lookup Built-in Functions coord, float lod)
vec4 shadow1DProjLod(sampler1DShadow sampler, vec4
Texture Lookup Built-in Functions coord, float lod)
vec4 shadow2DProjLod(sampler2DShadow sampler, vec4
Texture Lookup Built-in Functions coord, float lod)

The lookup is performed on the texture of the type encoded in the function name (1D, 2D, 3D, Cube) currently bound to the sampler represented by the sampler parameter. The “Proj” versions perform a projective divide on the texture coordinate before lookup. The divisor is the last component of the coordinate vector.

The “Lod” versions, available only in a vertex shader, specify the mipmap level-of-detail (LOD) from which to sample. The non-”Lod” versions sample from the base LOD when used by a vertex shader. Fragment shaders can use only the non-”Lod” versions, where the mipmap LOD is computed as usual based on texture coordinate derivatives. However, fragment shaders can supply an optional bias that will be added to the computed LOD. This bias parameter is not allowed in a vertex shader.

The “shadow” versions perform a depth texture comparison as part of the lookup (see Chapter 18, “Depth Textures and Shadows”).

Summary

In this chapter, you learned all the nuts and bolts of the OpenGL Shader Language (GLSL). We discussed all the variable types, operators, and flow control mechanisms. We also described how to use the entrypoints for loading and compiling shader objects and linking and using program objects. There was a lot of ground to cover here, but we made it through at a record pace.

This chapter concludes the boring lecture portion of our shader coverage. You now have a solid conceptual foundation for the remaining two chapters, which will provide practical examples of vertex and fragment shader applications using both low-level and high-level shader languages. The following chapters will prove much more enjoyable with all the textbook learning behind you.

Reference

glAttachObjectARB

Purpose:

Attaches an object to another container object.

Include File:

<glext.h>

Syntax:

void glAttachObjectARB(GLhandleARB containerObj, 
ReferenceGLhandleARB obj);

Description:

This function attaches an object to a container object. If the first argument is not a container object, if the second argument is already attached to the specified container object, or if the second object is not a type that can be attached to a container, an error is thrown. glLinkProgramARB must be called after glAttachObjectARB for the newly-attached objects to take effect.

Parameters:

containerObj

GLhandleARBThe container object to which the other object is being attached.

obj

GLhandleARBThe object being attached to the container object.

Returns:

None.

See Also:

glDetachObjectARB, glLinkProgramARB, glGetAttachedObjectsARB

glBindAttribLocationARB

Purpose:

Sets the location for a generic vertex attribute.

Include File:

<glext.h>

Syntax:

void glBindAttribLocationARB(GLhandleARB
GLhandleARB: programObj, GLuint index, 
                             const GLcharARB *name);

Description:

This function explicitly specifies the generic vertex attribute number for use by the specified attribute variable. Any attributes not explicitly bound will be bound automatically during linking. This routine can be called at any time, even before a vertex shader is attached to a program object, to reserve generic attribute locations. Also, glLinkProgramARB must be called again after glBindAttribLocationARB for the new location(s) to take effect.

Parameters:

programObj

GLhandleARBThe program object containing the vertex attribute.

index

GLuintThe number of the vertex attribute where this attribute will be located.

name

const GLcharARB *The name of the attribute variable.

Returns:

None.

See Also:

glGetAttribLocationARB, glGetActiveAttribARB, glLinkProgramARB, glVertexAttrib*ARB, glVertexAttribPointerARB

glCompileShaderARB

Purpose:

Compiles a shader.

Include File:

<glext.h>

Syntax:

void glCompileShaderARB(GLhandleARB shaderObj);

Description:

This function attempts to compile the shader text previously loaded into the shader object. The shader object flag GL_OBJECT_COMPILE_STATUS_ARB is set to GL_TRUE if the compile is successful and ready for linkage; otherwise, it's set to GL_FALSE. The shader object's info log may be updated to include information about the compile.

Parameters:

shaderObj

GLhandleARBThe shader object to compile.

Returns:

None.

See Also:

glGetInfoLogARB, glShaderSourceARB, glGetObjectParameter*vARB, glLinkProgramARB

glCreateProgramObjectARB

Purpose:

Creates a program object.

Include File:

<glext.h>

Syntax:

GLhandleARB glCreateProgramObjectARB(GLvoid);

Description:

This function creates a new program object and returns its handle.

Parameters:

None.

Returns:

GLhandleARBThe handle to the new program object.

See Also:

glCreateShaderObjectARB, glDeleteObjectARB, glUseProgramObjectARB, glLinkProgramARB

glCreateShaderObjectARB

Purpose:

Creates a shader object of the requested type.

Include File:

<glext.h>

Syntax:

GLhandleARB glCreateShaderObjectARB(GLenum
GLhandleARB: shaderType);

Description:

This function creates a new shader object of the specified type and returns its handle.

Parameters:

shaderType

GLenumThe type of shader object being created. It can be one of the following constants:

GL_VERTEX_SHADER_ARBCreate a vertex shader object.

GL_FRAGMENT_SHADER_ARBCreate a fragment shader object.

Returns:

GLhandleARBThe handle to the new shader object.

See Also:

glCreateProgramObjectARB, glDeleteObjectARB, glCompileShaderARB

glDeleteObjectARB

Purpose:

Deletes an object.

Include File:

<glext.h>

Syntax:

void glDeleteObjectARB(GLhandleARB obj);

Description:

If the specified object is not attached to any container object and is not a part of the current rendering state of any context, the object is deleted immediately. Otherwise, it is flagged for future deletion and won't be deleted until it's no longer attached to any container object and no longer part of the current rendering state of any context. When a container object is deleted, all objects attached to it become detached.

Parameters:

obj

GLhandleARBThe object to delete.

Returns:

None.

See Also:

glCreateProgramObject, glCreateShaderObjectARB, glGetObjectParameter*vARB, glUseProgramObjectARB

glDetachObjectARB

Purpose:

Detaches an object from a container object.

Include File:

<glext.h>

Syntax:

void glDetachObjectARB(GLhandleARB containerObj, 
GLhandleARB:GLhandleARB attachedObj);

Description:

This function detaches an object from a container object. If the detached object is flagged for deletion and not attached to any other container objects, it is deleted. glLinkProgramARB must be called after glDetachObjectARB for the newly-detached objects to take effect.

Parameters:

containerObj

GLhandleARBThe container object from which the other object is to be detached.

attachedObj

GLhandleARBThe object being detached.

Returns:

None.

See Also:

glAttachObjectARB, glLinkProgramARB, glGetAttachedObjectsARB

glGetActiveAttribARB

Purpose:

Gets information about active vertex attributes.

Include File:

<glext.h>

Syntax:

void glGetActiveAttribARB(GLhandleARB programObj, 
GLhandleARB:GLuint index, 
                          GLsizei maxLength, 
GLhandleARB:GLsizei *length, GLint *size,
                          GLenum *type, GLcharARB 
GLhandleARB:*name);

Description:

After a program object link has been attempted, this function can be called to find information about a particular vertex attribute variable, including its name, the length of its name, its size, and its type.

Parameters:

programObj

GLhandleARBThe program object being queried.

index

GLuintThe vertex attribute being queried.

maxLength

GLsizeiThe maximum number of characters that should be returned for the name.

length

GLsizei *A pointer to the location where the name length is returned. The length includes only characters actually returned and does not include the null terminator. If a NULL pointer is provided, no length is returned.

size

GLint *A pointer to the location where the attribute size is returned. This size, measured in units of the returned type, is currently always 1 but is part of the API in the event that attribute arrays become part of the OpenGL Shading Language at a later date.

type

GLenum *A pointer to the location where the attribute type is returned. The type will be one of the following constants:

GL_FLOATScalar floating-point value.

GL_FLOAT_VEC2_ARBTwo-component floating-point vector.

GL_FLOAT_VEC3_ARBThree-component floating-point vector.

GL_FLOAT_VEC4_ARBFour-component floating-point vector.

GL_FLOAT_MAT2_ARB2×2 floating-point matrix.

GL_FLOAT_MAT3_ARB3×3 floating-point matrix.

GL_FLOAT_MAT4_ARB4×4 floating-point matrix.

name

GLcharARB *A pointer to the location where the attribute name is returned as a null-terminated string.

Returns:

None.

See Also:

glGetAttribLocationARB, glBindAttribLocationARB, glGetVertexAttrib*vARB, glGetVertexAttribPointervARB

glGetActiveUniformARB

Purpose:

Gets information about active uniforms.

Include File:

<glext.h>

Syntax:

void glGetActiveUniformARB(GLhandleARB programObj,
GLcharARB *: GLuint index, 
                           GLsizei maxLength, 
GLcharARB *:GLsizei *length, GLint *size, 
                           GLenum *type, GLcharARB
GLcharARB *: *name);

Description:

After a program object link has been attempted, this function can be called to find information about a particular uniform variable, including its name, the length of its name, its size, and its type.

Parameters:

programObj

GLhandleARBThe program object being queried.

index

GLuintThe uniform being queried.

maxLength

GLsizeiThe maximum number of characters that should be returned for the name.

length

GLsizei *A pointer to the location where the name length is returned. The length includes only characters actually returned and does not include the null terminator. If a NULL pointer is provided, no length is returned.

size

GLint *A pointer to the location where the uniform array size is returned. This size is in terms of the returned type and is 1 for nonarrays.

type

GLenum *A pointer to the location where the uniform type is returned. The type will be one of the following constants:

GL_FLOATScalar floating-point value.

GL_FLOAT_VEC2_ARBTwo-component floating-point vector.

GL_FLOAT_VEC3_ARBThree-component floating-point vector.

GL_FLOAT_VEC4_ARBFour-component floating-point vector.

GL_INTScalar integer value.

GL_INT_VEC2_ARBTwo-component integer vector.

GL_INT_VEC3_ARBThree-component integer vector.

GL_INT_VEC4_ARBFour-component integer vector.

GL_BOOL_ARBScalar Boolean value.

GL_BOOL_VEC2_ARBTwo-component Boolean vector.

GL_BOOL_VEC3_ARBThree-component Boolean vector.

GL_BOOL_VEC4_ARBFour-component Boolean vector.

GL_FLOAT_MAT2_ARB2×2 floating-point matrix.

GL_FLOAT_MAT3_ARB3×3 floating-point matrix.

GL_FLOAT_MAT4_ARB4×4 floating-point matrix.

GL_SAMPLER_1D_ARBHandle for accessing 1D texture.

GL_SAMPLER_2D_ARBHandle for accessing 2D texture.

GL_SAMPLER_3D_ARBHandle for accessing 3D texture.

GL_SAMPLER_CUBE_ARBHandle for accessing cube-mapped texture.

GL_SAMPLER_1D_SHADOW_ARBHandle for accessing 1D depth texture with depth comparison.

GL_SAMPLER_2D_SHADOW_ARBHandle for accessing 2D depth texture with depth comparison.

name

GLcharARB *A pointer to the location where the uniform name is returned as a null-terminated string.

Returns:

None.

See Also:

glGetUniformLocationARB, glGetUniform*vARB, glUniform*ARB

glGetAttachedObjectsARB

Purpose:

Gets a list of objects attached to a container object.

Include File:

<glext.h>

Syntax:

void glGetAttachedObjectsARB(GLhandleARB
GLcharARB *: containerObj, GLsizei maxCount, 
                             GLsizei *count, 
GLcharARB *:GLhandleARB *obj);

Description:

This function returns a list of all the objects contained within another object. Specifically, it returns all the shader objects contained within a program object.

Parameters:

containerObj

GLhandleARBThe container object being queried.

maxCount

GLsizeiThe maximum number of object handles to return.

count

GLsizei *A pointer to the location where the count is returned. The count includes only handles actually returned. If a NULL pointer is provided, no count is returned.

obj

GLhandleARB *A pointer to an array of returned object handles.

Returns:

None.

See Also:

glAttachObjectARB, glDetachObjectARB, glDeleteObjectARB

glGetAttribLocationARB

Purpose:

Gets the location of a vertex attribute variable.

Include File:

<glext.h>

Syntax:

GLint glGetAttribLocationARB(GLhandleARB
GLhandleARB *: programObj, const GLcharARB *name);

Description:

After a program object has been successfully linked, this function returns the location of the vertex attribute variable with the specified name.

Parameters:

programObj

GLhandleARBThe program object being queried.

name

const GLcharARB *The vertex attribute variable name, null terminated.

Returns:

GLintThe location of the vertex attribute or –1 if no such attribute is active or if the name starts with the reserved prefix “gl_”. If name corresponds to an active matrix attribute, the location of the first column is returned.

See Also:

glGetActiveAttribARB, glBindAttribLocationARB, glLinkProgramARB, glVertexAttrib*ARB, glVertexAttribPointerARB

glGetHandleARB

Purpose:

Returns an object handle.

Include File:

<glext.h>

Syntax:

GLhandleARB glGetHandleARB(GLenum pname);

Description:

This function returns the handle to an object that is part of the current state.

Parameters:

pname

GLenumThe object handle from current state to return. It must be the constant GL_PROGRAM_OBJECT_ARB.

Returns:

GLhandleARBThe current program object or 0 if no such object is currently used.

See Also:

glCreateProgramObjectARB, glUseProgramObjectARB

glGetInfoLogARB

Purpose:

Gets information about the last compile or link.

Include File:

<glext.h>

Syntax:

void glGetInfoLogARB(GLhandleARB obj, GLsizei 
GLhandleARB:maxLength, GLsizei *length,
                     GLcharARB *infoLog);

Description:

Each shader object has an info log that contains information about the most recent compile attempt by that shader object. Similarly, each program object has an info log that contains information about the most recent link or validation attempt. This function provides access to these logs.

Parameters:

obj

GLhandleARBThe object whose information log is being queried.

maxLength

GLsizeiThe maximum number of characters that should be returned in the info log.

length

GLsizei *A pointer to the location where the length of the info log is returned. The length includes only characters actually returned and does not include the null terminator. If a NULL pointer is provided, no length is returned.

infoLog

GLcharARB *A pointer to the location where the info log text is returned as a null-terminated string.

Returns:

None.

See Also:

glCompileShaderARB, glLinkProgramARB, glValidateProgramARB

glGetObjectParameter*vARB

Purpose:

Gets information about the specified object.

Include File:

<glext.h>

Syntax:

void glGetObjectParameterfvARB(GLhandleARB obj, 
GLcharARB *:GLenum pname, GLfloat *params);
void glGetObjectParameterivARB(GLhandleARB obj, 
GLcharARB *:GLenum pname, GLint *params);

Description:

This function queries a property of the specified program or shader object.

Parameters:

obj

GLhandleARBThe object being queried.

pname

GLenumThe property being queried. It can be one of the following constants:

GL_OBJECT_TYPE_ARBReturns GL_PROGRAM_OBJECT_ARB if the object is a program object and GL_SHADER_OBJECT_ARB if the object is a shader object.

GL_OBJECT_SUBTYPE_ARBReturns either GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB if the object is a shader object.

GL_OBJECT_DELETE_STATUS_ARBReturns 1 or 1.0 if the object's delete flag is set; otherwise, 0 or 0.0 is returned.

GL_OBJECT_COMPILE_STATUS_ARBReturns 1 or 1.0 if the shader object's most recent compile was successful.

GL_OBJECT_LINK_STATUS_ARBReturns 1 or 1.0 if the program object's most recent link was successful.

GL_OBJECT_VALIDATE_STATUS_ARBReturns 1 or 1.0 if the program object's most recent validation was successful.

GL_OBJECT_INFO_LOG_LENGTH_ARBReturns the length in characters of the object's info log, including the null terminator, or 0 if there is no info log.

GL_OBJECT_ATTACHED_OBJECTS_ARBReturns the number of shader objects attached to this program object.

GL_OBJECT_ACTIVE_UNIFORMS_ARBReturns the number of uniforms active in this program object.

GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARBReturns the length of this program object's longest active uniform variable name.

GL_OBJECT_SHADER_SOURCE_LENGTH_ARBReturns the length of this shader object's shader text, including the null terminator.

GL_OBJECT_ACTIVE_ATTRIBUTES_ARBReturns the number of vertex attributes active in this program object.

GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARBReturns the length of this program object's longest active vertex attribute variable name.

params

GLfloat */ GLint *A pointer to the location where the result will be stored.

Returns:

None.

See Also:

glShaderSourceARB, glCompileShaderARB, glLinkProgramARB, glAttachObjectARB, glDetachObjectARB, glCreateShaderObjectARB, glCreateProgramObjectARB, glDeleteObjectARB

glGetShaderSourceARB

Purpose:

Gets a shader object's source text.

Include File:

<glext.h>

Syntax:

void glGetShaderSourceARB(GLhandleARB obj, GLsizei
GLfloat */ GLint *: maxLength, GLsizei *length,
                          GLcharARB *source);

Description:

This function returns a concatenation of all the shader source text previously supplied via glShaderSourceARB.

Parameters:

obj

GLhandleARBThe shader object being queried.

maxLength

GLsizeiThe maximum number of characters that should be returned.

length

GLsizei *A pointer to the location where the length of the source text is returned. The length includes only characters actually returned and does not include the null terminator. If a NULL pointer is provided, no length is returned.

source

GLcharARB *A pointer to the location where the shader source text is returned as a null-terminated string.

Returns:

None.

See Also:

glShaderSourceARB, glCreateShaderObjectARB, glCompileShaderARB

glGetUniform*vARB

Purpose:

Gets the value(s) of a uniform variable.

Include File:

<glext.h>

Syntax:

void glGetUniformfvARB(GLhandleARB programObj, 
GLcharARB *:GLint location, 
                       GLfloat *params);
void glGetUniformivARB(GLhandleARB programObj, 
GLcharARB *:GLint location, GLint *params);

Description:

If the program object has been successfully linked, and a valid uniform location has been provided, as by glGetUniformLocationARB, this function returns the value or values of the uniform variable at that location. The number of values returned is based on the type of the uniform. Each element of an array variable must be queried independently. If the variable is a matrix, its data is returned in column-major order.

Parameters:

programObj

GLhandleARBThe program object being queried.

location

GLintThe location of the uniform variable being queried.

params

GLfloat */ GLint *A pointer to the location where the uniform value(s) will be stored.

Returns:

None.

See Also:

glUniform*ARB, glGetUniformLocationARB, glGetActiveUniformARB

glGetUniformLocationARB

Purpose:

Gets the location of a uniform variable.

Include File:

<glext.h>

Syntax:

GLint glGetUniformLocationARB(GLhandleARB
GLfloat */ GLint *: programObj, const GLcharARB *name);

Description:

After a program object has been successfully linked, this function returns the location of the uniform variable with the specified name.

Parameters:

programObj

GLhandleARBThe program object being queried.

name

const GLcharARB *The uniform variable name, null terminated. The name cannot be a structure, array of structures, or a subcomponent of a vector or matrix. The . and [] operators can be used to identify members of a structure or array. The first element of an array can be queried either using just the name of the array, or with [0] appended.

Returns:

GLintThe location of the uniform or –1 if no such uniform is active or if the name starts with the reserved prefix "gl_".

See Also:

glGetActiveUniformARB, glLinkProgramARB, glUniform*ARB, glGetUniform*vARB

glLinkProgramARB

Purpose:

Links a program object.

Include File:

<glext.h>

Syntax:

void glLinkProgramARB(GLhandleARB programObj);

Description:

This function attempts to link the previously compiled shader objects contained within the specified program object. The program object flag GL_OBJECT_LINK_STATUS_ARB is set to GL_TRUE if the link is successful and ready for use; otherwise, it's set to GL_FALSE. The program object's info log will be updated to include information about the link.

Parameters:

programObj

GLhandleARBThe program object to link.

Returns:

None.

See Also:

glGetInfoLogARB, glGetObjectParameter*vARB, glCompileShaderARB, glUseProgramObjectARB

glShaderSourceARB

Purpose:

Loads source text into a shader object.

Include File:

<glext.h>

Syntax:

void glShaderSourceARB(GLhandleARB shaderObj, 
GLhandleARB:GLsizei count, 
                       const GLcharARB **string, 
GLhandleARB:const GLint *length);

Description:

This function loads a shader object with one or more strings of shader source text. Any pre-existing source text is replaced with the new text. For the new shader source to take effect, the shader object must be freshly compiled, and the program object(s) it is attached to must be freshly linked.

Parameters:

shaderObj

GLhandleARBThe shader object whose source text is being loaded.

count

GLsizeiThe number of strings to load.

string

const GLcharARB **A pointer to an array of one or more strings, each representing part of the shader source text.

length

const GLint *A pointer to an array of lengths, representing the length of each shader source string, excluding the null terminator. If a length is –1, the corresponding string is guaranteed to be null-terminated. If length is NULL, all strings are guaranteed to be null-terminated.

Returns:

None.

See Also:

glCompileShaderARB, glGetShaderSourceARB, glCreateShaderObjectARB

glUniform*ARB

Purpose:

Load uniform variable values.

Include File:

<glext.h>

Syntax:

void glUniform1fARB(GLint location, GLfloat v0);
void glUniform2fARB(GLint location, GLfloat v0, 
const GLint *:GLfloat v1);
void glUniform3fARB(GLint location, GLfloat v0, 
const GLint *:GLfloat v1, GLfloat v2);
void glUniform4fARB(GLint location, GLfloat v0, 
const GLint *:GLfloat v1, 
                                    GLfloat v2, 
const GLint *:GLfloat v3);
void glUniform1iARB(GLint location, GLint v0);
void glUniform2iARB(GLint location, GLint v0, 
const GLint *:GLint v1);
void glUniform3iARB(GLint location, GLint v0, 
const GLint *:GLint v1, GLint v2);
void glUniform4iARB(GLint location, GLint v0, 
const GLint *:GLint v1, GLint v2, GLint v3);
void glUniform1fvARB(GLint location, GLsizei count
const GLint *:, const GLfloat *value);
void glUniform2fvARB(GLint location, GLsizei count
const GLint *:, const GLfloat *value);
void glUniform3fvARB(GLint location, GLsizei count
const GLint *:, const GLfloat *value);
void glUniform4fvARB(GLint location, GLsizei count
const GLint *:, const GLfloat *value);
void glUniform1ivARB(GLint location, GLsizei count
const GLint *:, const GLint *value);
void glUniform2ivARB(GLint location, GLsizei count
const GLint *:, const GLint *value);
void glUniform3ivARB(GLint location, GLsizei count
const GLint *:, const GLint *value);
void glUniform4ivARB(GLint location, GLsizei count
const GLint *:, const GLint *value);
void glUniformMatrix2fvARB(GLint location, GLsizei
const GLint *: count, GLboolean transpose, const GLfloat *value);
void glUniformMatrix3fvARB(GLint location, GLsizei
const GLint *: count, GLboolean transpose, const GLfloat *value);
void glUniformMatrix4fvARB(GLint location, GLsizei
const GLint *: count, GLboolean transpose, const GLfloat *value);

Description:

This function loads one or more values into the specified uniform variable of the currently used program object. The size and type of the function must match the size and type of the uniform variable, except for Boolean type uniforms. For Boolean uniforms, either the floating-point or integer functions can be used, where 0.0 or 0 is converted to GL_FALSE and all other values are converted to GL_TRUE. If no program object is in use, this function will fail and generate an error.

Parameters:

location

GLintThe location of the uniform variable to load, as returned from glGetUniformLocationARB. If an array, this is the starting location for loading array elements.

count

GLsizeiThe number of array elements to load or 1 if not an array.

transpose

GLbooleanWhether or not to transpose the specified matrix elements before storing them in OpenGL state. If GL_TRUE, the matrix is interpreted as originating in row-major order, and is transposed to column-major order before storing. If GL_FALSE, the matrix is interpreted as being in column-major order already, which is the order in which GLSL operates on matrices.

v0, v1, v2, v3

GLfloat / GLintThe values to load into the uniform variable.

value

GLfloat */ GLint *A pointer to the values to load into the uniform variable.

Returns:

None.

See Also:

glGetUniform*vARB, glGetUniformLocationARB, glGetActiveUniformARB, glLinkProgramARB

glUseProgramObjectARB

Purpose:

Sets the current program object.

Include File:

<glext.h>

Syntax:

void glUseProgramObjectARB(GLhandleARB programObj);

Description:

After a program object has been successfully linked, this function installs its executable code as part of the current rendering state. It can also be used to deinstall all executable code and return to a fully fixed functionality pipeline. Once installed, executable code can be changed only by first relinking, at which point calling this function again is unnecessary.

Parameters:

programObj

GLhandleARBThe program object to be used or 0 to revert to fixed functionality.

Returns:

None.

See Also:

glLinkProgramARB, glGetHandleARB, glUniform*ARB

glValidateProgramARB

Purpose:

Validates a program object against current state.

Include File:

<glext.h>

Syntax:

void glValidateProgramARB(GLhandleARB programObj);

Description:

Without taking the current state into consideration, it is impossible to know whether a given program object will execute when first used for rendering, even if it linked successfully. This function validates the specified program object against the current OpenGL state to detect any problems or inefficiencies. The program object flag GL_OBJECT_VALIDATE_STATUS_ARB is set to GL_TRUE if the validation is successful and the program object is guaranteed to work with the current state; otherwise, it's set to GL_FALSE. The program object's info log will be updated to include information about the validation.

Parameters:

programObj

GLhandleARBThe program object to validate.

Returns:

None.

See Also:

glGetInfoLogARB, glGetObjectParameter*vARB, glLinkProgramARB, glUseProgramObjectARB

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

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