Here are the key points to understand about how all the pieces fit together at execution time.
When installed as part of current state, the executable created for the vertex processor is executed once for every vertex provided to OpenGL.
When installed as part of current state, the executable created for the fragment processor is executed once for every fragment that is produced by rasterization.
When vertex or fragment shaders are used, the corresponding fixed functionality is disabled. Shaders must implement such functionality themselves if it is desired.
Varying variables defined in a vertex shader are per-vertex values that are output from the vertex processor. Rasterization is the process that causes the per-vertex values to be interpolated and per-fragment values to be generated. The per-fragment values become the input to the fragment processor and are accessed in the fragment shader with the same varying variable name as was used in the vertex shader.
An application can communicate directly with a vertex shader in two ways: by using attribute variables and by using uniform variables.
Attribute variables are expected to change frequently and may be supplied by the application as often as every vertex.
Applications can pass arbitrary vertex data to a vertex shader with user-defined attribute variables.
Applications can pass standard vertex attributes (color, normal, texture coordinates, position, etc.) to a vertex shader with built-in attribute variables.
An application communicates directly with a fragment shader with uniform variables.
Uniform variables are expected to change relatively infrequently (at a minimum, they are constant for an entire graphics primitive).
The compiler and linker for the language are contained within OpenGL, but tools for compiling, linking, and debugging shaders can exist outside of OpenGL as well.
To summarize, the following are the most important points about the OpenGL Shading Language.
The language is based on the syntax of C.
Basic structure and many keywords are the same as in C.
Vectors and matrices are included in the language as basic types.
Type qualifiers attribute, uniform, and varying are added to describe variables that manage shader I/O.
Variables of type attribute allow the communication of frequently changing values from the application to the vertex shader.
Variables of type varying are the output from a vertex shader and the input to a fragment shader.
Variables of type uniform allow the application to provide relatively infrequently changing values to both vertex shaders and fragment shaders.
The data type sampler is added for accessing textures.
Built-in variable names can be used to access standard OpenGL state and to communicate with OpenGL fixed functionality.
A variety of built-in functions perform common graphics operations.
Function declarations are required, and overloading based on number and type of arguments is supported as in C++.
Variables can be declared when needed.
Create one or more (empty) shader objects by calling glCreateShader.
Provide source code for these shaders by calling glShaderSource.
Compile each of the shaders by calling glCompileShader.
Create a program object by calling glCreateProgram.
Attach all the shader objects to the program object by calling glAttachShader.
Link the program object by calling glLinkProgram.
Install the executable program as part of OpenGL's current state by calling glUseProgram.
After these steps, subsequent graphics primitives will be drawn with the shaders you've provided rather than with OpenGL's defined fixed functionality pipeline.