The OpenGL Shading Language (GLSL) is the principal shading language for OpenGL. While, thanks to OpenGL Extensions, there are several shading languages available for use in OpenGL, GLSL (and SPIR-V) are supported directly by OpenGL without extensions.

GLSL is a C-style language. The language has undergone a number of version changes, and it shares the deprecation model of OpenGL. The current version of GLSL is 4.60.

Compilation model

GLSL is quite unique among shading languages due to its compilation model. It's compilation model is more like the standard C paradigm. Compilation is overseen by a number of object types. Note that these do not follow the standard OpenGL Objects paradigm.

Terminology

According to GLSL's standard terminology, a shader is just a compiled set of strings for a particular programmable stage; it does not even need to have the complete code for that stage. A program is a fully linked program that covers multiple programmable stages.

For the sake of clarity, we will adjust this slightly. When the term shader is used, it will be synonymous with the GLSL concept of program. To refer to a GLSL shader, the term shader object will be used.

Language

GLSL is a lot like C/C++ in many ways. It supports most of the familiar structural components (for-loops, if-statements, etc). But it has some important language differences.

Standard library

The OpenGL Shading Language defines a number of standard functions. Some standard functions are specific to certain shader stages, while most are available in any stage. There is reference documentation for these functions available here.

Interface blocks

Certain variable definitions can be grouped into interface blocks. These can be used to make communication between different shader stages easier, or to allow storage for variables to come from a buffer object.

Because of this, there is a mapping layer for the program's inputs and outputs. The vertex shader's input names are mapped to attribute indices, while the fragment shader's output names are mapped to draw buffer indices. This mapping can be created before the program is linked. If it is not, or if the mapping does not cover all of the inputs and outputs, then the linker will automatically define what indices are mapped to which unmapped input or output names. This auto-generated mapping can be queried by the user after the program is linked.

Setting uniforms

Uniforms in GLSL a shader variables that are set from user code, but only are allowed to change between different glDraw* calls. Uniforms can be queried and set by the code external to a particular shader. Uniforms can be arranged into blocks, and the data storage for these blocks can come from buffer objects.

Setting samplers

Samplers are special types which must be defined as uniforms. They represent bound textures in the OpenGL context. They are set like integer, 1D uniform values.

Error Checking

This piece of code shows the process of loading a vertex and fragment shaders. Then it compiles them and also checks for errors. The idea here is to encourage newcomers to GLSL to always check for errors. It is in C++ but that doesn't matter.

Note that the process of loading and compiling shaders hasn't changed much over the different GL versions.

// Read our shaders into the appropriate buffersstd::stringvertexSource=// Get source code for vertex shader.std::stringfragmentSource=// Get source code for fragment shader.// Create an empty vertex shader handleGLuintvertexShader=glCreateShader(GL_VERTEX_SHADER);// Send the vertex shader source code to GL// Note that std::string's .c_str is NULL character terminated.constGLchar*source=(constGLchar*)vertexSource.c_str();glShaderSource(vertexShader,1,&source,0);// Compile the vertex shaderglCompileShader(vertexShader);GLintisCompiled=0;glGetShaderiv(vertexShader,GL_COMPILE_STATUS,&isCompiled);if(isCompiled==GL_FALSE){GLintmaxLength=0;glGetShaderiv(vertexShader,GL_INFO_LOG_LENGTH,&maxLength);// The maxLength includes the NULL characterstd::vector<GLchar>infoLog(maxLength);glGetShaderInfoLog(vertexShader,maxLength,&maxLength,&infoLog[0]);// We don't need the shader anymore.glDeleteShader(vertexShader);// Use the infoLog as you see fit.// In this simple program, we'll just leavereturn;}// Create an empty fragment shader handleGLuintfragmentShader=glCreateShader(GL_FRAGMENT_SHADER);// Send the fragment shader source code to GL// Note that std::string's .c_str is NULL character terminated.source=(constGLchar*)fragmentSource.c_str();glShaderSource(fragmentShader,1,&source,0);// Compile the fragment shaderglCompileShader(fragmentShader);glGetShaderiv(fragmentShader,GL_COMPILE_STATUS,&isCompiled);if(isCompiled==GL_FALSE){GLintmaxLength=0;glGetShaderiv(fragmentShader,GL_INFO_LOG_LENGTH,&maxLength);// The maxLength includes the NULL characterstd::vector<GLchar>infoLog(maxLength);glGetShaderInfoLog(fragmentShader,maxLength,&maxLength,&infoLog[0]);// We don't need the shader anymore.glDeleteShader(fragmentShader);// Either of them. Don't leak shaders.glDeleteShader(vertexShader);// Use the infoLog as you see fit.// In this simple program, we'll just leavereturn;}// Vertex and fragment shaders are successfully compiled.// Now time to link them together into a program.// Get a program object.GLuintprogram=glCreateProgram();// Attach our shaders to our programglAttachShader(program,vertexShader);glAttachShader(program,fragmentShader);// Link our programglLinkProgram(program);// Note the different functions here: glGetProgram* instead of glGetShader*.GLintisLinked=0;glGetProgramiv(program,GL_LINK_STATUS,(int*)&isLinked);if(isLinked==GL_FALSE){GLintmaxLength=0;glGetProgramiv(program,GL_INFO_LOG_LENGTH,&maxLength);// The maxLength includes the NULL characterstd::vector<GLchar>infoLog(maxLength);glGetProgramInfoLog(program,maxLength,&maxLength,&infoLog[0]);// We don't need the program anymore.glDeleteProgram(program);// Don't leak shaders either.glDeleteShader(vertexShader);glDeleteShader(fragmentShader);// Use the infoLog as you see fit.// In this simple program, we'll just leavereturn;}// Always detach shaders after a successful link.glDetachShader(program,vertexShader);glDetachShader(program,fragmentShader);