A fragment shader processes…fragments. The fragments that were discovered in the rasterization process, and whose attributes were computed in the interpolation phase, are now fed, one by one, to the fragment shader. This shader is not optional, unless transform feedback is being used.
Fragment shaders can access the fragment, or pixel, position, and all the interpolated data computed in the rasterization process.
A fragment shader performs computations based on these attributes and the pixels position. The pixel’s position is fixed, i.e. a fragment shader can not choose to write the attributes of other pixel. However, it can change the pixel’s depth.
The fragment shader does not have access to the framebuffer, neither at the current pixel’s position, nor at any other pixel position. The fragment shader, similarly to the vertex shader, only has acess to the current pixel and its associated data.
As in the previous stages the fragment shader has access to bound textures.
The following built-in variables are available in a fragment shader:
gl_FragCoord
: contains the fragmens coordinate(xf, yf, zf, wf)
, where(xf, yf)
is the pixels position on the window,zf
is the depth, andwf
is 1/wc
, wherewc
is the component of the fragments clip space positiongl_FrontFacing
: tells the orientation of the primitive that originated the pixel. Note that if face culling is enabled then this value will be the same for all pixels.gl_PrimitiveID
: This variable is an output of the geometry shader. If no geometry shader is present, the value reflects the index of the primitive in the OpenGL draw command.gl_SampleMaskIn
: This variable reports on the set of fragment samples covered by the primtive that generated the pixel. This is only useful if working with multisample buffers.gl_SampleID
: holds the sample number of the sample being currently processed.gl_NumSamples
: the number of samples being used.gl_SamplePosition
: the position inside the pixel of the sample being processed.
Note: gl_PrimitiveID
, gl_SampleMaskIn
, gl_SampleID
,
gl_NumSamples
, and gl_SamplePosition
are only available in version 4.1.
Regarding outputs, these can range, in number, from 1 to GL_MAX_DRAW_BUFFERS
. By default an application has a single color output, and its type is a
vec4
. An application should bind user-defined variables to color outputs. There may be more than one color output if using frame buffer objects.
The shader below is probably the simplest fragment shader we can write. Not very interesting, it just paints everything red!
1
2
3
4
5
6
7
8
|
#version 150 out vec4 colorOut; void
main() { colorOut = vec4(1.0, 0.0, 0.0, 1.0); } |
In the shader above we should bind the variable colorOut
to output location 0, the default location when not using frame buffer objects, using the following function:
void glBindFragDataLocation(GLuint program, GLuint colorNumber, const char *name);
Params:
- program: the program object handle
- colorNumber: the output location to bind the variable to
- name: the name of the variable
So, considering the shader above, and assuming
p
as a handle to our program, we could write in our application the following OpenGL instruction:
1
|
glBindFragDataLocation(p, 0,
"colorOut" ); |
Note that the binding does not take effect until the program is linked.
Locations for the output variables can also be hard-coded in the shader itself using layout qualifiers. The declaration of the
colorOut
variable can include a layout qualifier that establishes its location, as in the following example:
1
|
layout(location = 0) out vec4 colorOut; |