4.2. The Fragment Processor
The fragment processor executes a fragment shader and replaces the texturing, color sum, and fog fragment operations. Specifically, when the fragment processor is executing a fragment shader, the following fixed functionality operations are affected:
The behavior of the following operations does not change:
The basic operation of the fragment processor was discussed in Section 2.3.2. As shown in Figure 2.3, data can come into the fragment shader through varying variables (built in or user defined), uniform variables (built in or user defined), special input variables, or texture maps. Data exits the fragment processor through special fragment shader output variables. Built-in constants (described in Section 4.4) are also accessible from within a fragment shader.
Like vertex shaders, the behavior of a fragment shader is undefined when the frame buffer is configured as a color index buffer rather than as an RGBA buffer (i.e., OpenGL is in color index mode).
4.2.1. Varying Variables
The following built-in varying variables can be read in a fragment shader. The gl_Color and gl_SecondaryColor names are the same as built-in attribute variable names available in the vertex shader. However, the names do not conflict because attributes are visible only in vertex shaders and the following are only visible in fragment shaders:
varying vec4 gl_Color; varying vec4 gl_SecondaryColor; varying vec4 gl_TexCoord; // at most will be gl_MaxTextureCoords varying float gl_FogFragCoord;
The values in gl_Color and gl_SecondaryColor are derived automatically from gl_FrontColor, gl_BackColor, gl_FrontSecondaryColor, and gl_BackSecondaryColor as part of fixed functionality processing that determines whether the fragment belongs to a front facing or a back facing primitive (see Section 4.5.1). If fixed functionality is used for vertex processing, gl_FogFragCoord is either the z-coordinate of the fragment in eye space or the interpolated value of the fog coordinate, depending on whether the fog coordinate source is currently set to GL_FRAGMENT_DEPTH or GL_FOG_COORDINATE. The gl_TexCoord array contains either the values of the interpolated gl_TexCoord values from a vertex shader or the texture coordinates from the fixed functionality vertex processing. No automatic division of texture coordinates by their q-component is performed.
When the fragment shader is processing fragments resulting from the rasterization of a pixel rectangle or bitmap, results are undefined if the fragment shader uses a varying variable that is not a built-in varying variable. In this case, the values for the built-in varying variables are supplied by the current raster position and the values contained in the pixel rectangle or bitmap because a vertex shader is not executed.
Fragment shaders also obtain input data from user-defined varying variables. Both built-in and user-defined varying variables contain the result of perspective-correct interpolation of values that are defined at each vertex.
4.2.2. Uniform Variables
As described in Section 4.1.2, OpenGL state is available to both vertex shaders and fragment shaders through built-in uniform variables that begin with the reserved prefix "gl_". The list of uniform variables that can be used to access OpenGL state is provided in Section 4.3.
User-defined uniform variables can be defined and used within fragment shaders in the same manner as they are used within vertex shaders. OpenGL API calls are provided to set their values (see Section 7.8 for complete details).
The implementation-dependent limit that defines the amount of storage available for uniform variables in a fragment shader can be queried with glGet with the symbolic constant GL_MAX_FRAGMENT_UNIFORM_COMPONENTS. This limit refers to the storage for the combination of built-in uniform variables and user-defined uniform variables that are actually used in a fragment shader. It is defined in terms of components, where a component is the size of a float.
4.2.3. Special Input Variables
The variable gl_FragCoord is available as a read-only variable from within fragment shaders, and it holds the window relative coordinates x, y, z, and 1/w for the fragment. This window position value is the result of the fixed functionality that interpolates primitives after vertex processing to generate fragments. The z component contains the depth value as modified by the polygon offset calculation. This built-in variable allows implementation of window position-dependent operations such as screen-door transparency (e.g., use discard on any fragment for which gl_FragCoord.x is odd or gl_FragCoord.y is odd, but not both).
The fragment shader also has access to the read-only built-in variable gl_FrontFacing whose value is true if the fragment belongs to a front-facing primitive, and false otherwise. This value can be used to select between two colors calculated by the vertex shader to emulate two-sided lighting, or it can be used to apply completely different shading effects to front and back surfaces. A fragment derives its facing direction from the primitive that generates the fragment. All fragments generated by primitives other than polygons, triangles, or quadrilaterals are considered to be front facing. For all other fragments (including fragments resulting from polygons drawn with a polygon mode of GL_POINT or GL_LINE), the determination is made by examination of the sign of the area of the primitive in window coordinates. This sign can possibly be reversed, depending on the last call to glFrontFace. If the sign is positive, the fragments are front facing; otherwise, they are back facing.
These special input variables have global scope and can be referenced only from within a fragment shader. They are intrinsically declared with the following types:
vec4 gl_FragCoord; bool gl_FrontFacing;
4.2.4. Special Output Variables
The primary purpose of a fragment shader is to compute values that will ultimately be written into the frame buffer. Unless the keyword discard is encountered, the output of the fragment shader goes on to be processed by the fixed function operations at the back end of the OpenGL pipeline. Fragment shaders send their results on to the back end of the OpenGL pipeline by using the built-in variables gl_FragColor, gl_FragData, and gl_FragDepth. These built-in fragment shader variables have global scope, and they may be written more than once by a fragment shader. If they are written more than once, the last value assigned is the one used in the subsequent operations. They can also be read back after they have been written. Reading them before writing them results in undefined behavior.
The color value that is to be written into the frame buffer (assuming that it passes through the various back-end fragment processing stages unscathed) is computed by the fragment shader and stored in the built-in variable gl_FragColor. As it exits the fragment processor, each component of gl_FragColor is clamped to the range [0,1] and converted to fixed point with at least as many bits as are in the corresponding color component in the destination frame buffer. Most shaders compute a value for gl_FragColor, but it is not required that this value be computed by all fragment shaders. It is perfectly legal for a shader to compute values for gl_FragDepth or gl_FragData instead. The shader could also use the discard keyword to mark the fragment as one to be discarded rather than used to update the frame buffer. Note that if subsequent fixed functionality consumes fragment color and an execution of a fragment shader does not write a value to gl_FragColor, the behavior is undefined.
If depth buffering is enabled and a shader does not write gl_FragDepth, the fixed function value for depth is used as the fragment's depth value. Otherwise, writing to gl_FragDepth establishes the depth value for the fragment being processed. As it exits the fragment processor, this value is clamped to the range [0,1] and converted to fixed point with at least as many bits as are in the depth component in the destination frame buffer. Fragment shaders that write to gl_FragDepth should take care to write to it for every execution path through the shader. If it is written in one branch of a conditional statement but not the other, the depth value will be undefined for some execution paths.
The z component of gl_FragCoord contains the depth value resulting from the preceding fixed function processing. It contains the value that would be used for the fragment's depth if the shader contained no writes to gl_FragDepth. This component can be used to achieve an invariant result if a fragment shader conditionally computes gl_FragDepth but otherwise wants the fixed functionality fragment depth.
The values written to gl_FragColor and gl_FragDepth do not need to be clamped within a shader. The fixed functionality pipeline following the fragment processor clamps these values, if needed, to the range required by the buffer into which the fragment will be written.
gl_FragData is an array that can be assigned values that are written into one or more offscreen buffers. The size of this array is implementation dependent and can be queried with glGet with the symbolic constant GL_MAX_DRAW_BUFFERS. The offscreen buffers that are modified as a result of writing values into gl_FragData within a fragment shader are specified with glDrawBuffers. The value written into gl_FragData updates the first buffer in the list specified in the call to glDrawBuffers, the value written into gl_FragData updates the second buffer in the list, and so on. If subsequent fixed function processing consumes a value for gl_FragData[i] but this value is never written by the fragment shader, then the data consumed by the fixed function processing is undefined.
A fragment shader may assign values to gl_FragColor or gl_FragData but not both. If a shader executes the discard keyword, the fragment is discarded, no update of the frame buffer contents is performed, and the values of gl_FragDepth, gl_FragData and gl_FragColor become irrelevant.
The fragment shader output variables have global scope, can be referenced only from within a fragment shader, and are intrinsically declared with the following types:
vec4 gl_FragColor; vec4 gl_FragData[gl_MaxDrawbuffers]; float gl_FragDepth;