The OpenGL Shading Language (GLSL) is the shading language for OpenGL. It's a C-style language and the focus on these pages are version 4.50. The source code are compiled at runtime by OpenGl and all the fun details on how that is done is in the OpenGL Shaders section.
The built-in functions in GLSL is called the Standard library. Some functions are specific to certain shader stages.
[Storage_Qualifier] Type Name
These can be declared before a variable to modify the behavior of a global or local variable. Two deprecated qualifiers are attribute and varying. attribute was used for input to the vertex shader and varying to setup variables to send data from the vertex shader to the fragment shader. As there are now more then two possible shader stages in/out should be used instead.
- const: A const value cannot be changed after it is initialized.
- in/out: This is used on global variables to link the data between shader stages, see the In & Out section below.
- uniform: Can be used on global variables and Interface blocks. They value will stay the same for the rendering of a primitive. These values can be set with the OpenGL API.
- Scalar: bool, int, uint, float and double.
- Vector: A float vector type name is vec* where * is the number of components (2-4). Non float type are created by adding the first character of the type to the name. Ex ivec3 or dvec2.
- Matrix: For square float matrix there is mat2, mat3 and mat4. Other matrices are formed with matCxR with C colums and R rows. Create a double matrix by adding d befor the name. Ex mat3x2 or dmat3.
GLSL have some built-in variables for the various shader stages. Predefined variables start with "gl_".
Vertex shader - Inputs
in int gl_VertexID; // Index of the vertex being processed.
in int gl_InstanceID; // Index of the instance when doing instanced rendering, else 0.
out vec4 gl_Position; // Clip-space output position of vertex.
out float gl_PointSize; // Size of point if point rendering.
Fragment shader - Inputs
in vec4 gl_FragCoord; // Windows space of fragment. Z will be written to the depth buffer.
in bool gl_FrontFacing; // True if fragment generated by front-face primitives.
in vec2 gl_PointCoord; // Location of fragment within a point primitive.
out float gl_FragDepth; // The fragments depth. If not written it will use the gl_FragCoord.z value.
GLSL use the standard c++ set of statements.
Selection: if-else and switch-case.
Iteration: for, while and do-while.
Jump: break, continue and return.
Exit: return in main(). discard is fragment shader only and cause the resultat to discarded and ignored by the rest of the pipeline.
The first directive in a glsl source file should be the GLSL version that will be used to compile the code. Version numbers are now in sync with the OpenGl version number but for older numbers look on the version page. If one fails to set a version number it will use the ancient one of 1.10.
In & Out
Global variables declared with the in qualifier are input variables for the shader stage. They will get the values by the previous stages out variables or if it is the first stage from the vertex buffers. Global variables declared with the out qualifier are output variables for the sahder stage. They pass data on to the next stages in variable or the opengl framebuffer.
Start Stage (Vertex Shader)
In values in the vertex shader are called vertex attributes. Each attribute is assigned one or more vertex attribute indices. The easy way to do it is with the location syntax in the shader. A matrix takes a index for every column and a an array a index per element. So an mat4 that is assigned index 3 will use index 3,4,5 and 6. The max number of attributes is GL_MAX_VERTEX_ATTRIBS and 16 seems like the common lowest value. It is then possible to get the attribute location to setup data for the program on use glGetAttribLocation. More details in the OpenGL Shaders section.
layout(location = 2) in vec4 v_normal;
For to shader stages to match and be used in a program they must have the same in and out variables (or uniform blocks) with matching name, order, types and qualifiers. In short a copy/paste of the whole thing where you switch in to out :). The match is checked at link time mostly.
End Stage (Fragment Shader)
The output from the fragment shaders represents a series of colors. The allowed types are floats, intergers, vectors of these types and also arrays. Each variable will be assigned a number when the program is linked and that number is used as an index into the parameters to glDrawBuffers to pick the color buffer to write to. There are three ways to get the get the number glsl assign to each variable. The worst is to let glsl set the number when it links the program and use glGetFragDataLocation to get it. The middle option is to set it yourself before linking the program with glBindFragDataLocation. The simplest option is to set it in the GLSL code with a layout.
layout(location = 2) out vec4 smileyColor;
Fragment Shader Outputs - Through The Ages
#if, #else, #elif, #endif
fast trisect in GLSL - 2020
Faster Gaussian Blur in GLSL - 2012
OpenGL Clip Planes - 2012
Simple Introduction to Geometry Shaders in GLSL (Part 2) - 2011
Simplex Noise in GLSL - 2011
Silhouette Extraction - 2010
Fog in GLSL - 2007