Difference between revisions of "GLSL Object"

From OpenGL.org
Jump to: navigation, search
(Links to API functions)
(Program introspection)
(3 intermediate revisions by the same user not shown)
Line 7: Line 7:
 
GLSL uses a more complicated model based on the compilation of C programs. In C, a compilation unit, typically a single source file that may include several external header files, is compiled into an object file. A number of object files are then linked into a single program.
 
GLSL uses a more complicated model based on the compilation of C programs. In C, a compilation unit, typically a single source file that may include several external header files, is compiled into an object file. A number of object files are then linked into a single program.
  
GLSL operates in a similar fashion. A set of source files, given as a series of strings, are compiled into a shader object. This is the analog of an object file. Unlike typical shading languages, there is no requirement that this shader object represent a full shader stage. The only limitation is that it can only compile code that is appropriate for a single, specific shader stage.
+
GLSL operates in a similar fashion. A set of source files, given as a series of strings, are compiled into a shader object. This is the analog of an object file. Unlike typical shading languages, there is no requirement that this shader object represent the ''full code'' for a shader stage. The only limitation is that it can only contain code that is appropriate for a single, specific shader stage.
  
Shader objects are useless in that form, just as object files from compiled C programs are useless directly. Shader objects must be linked into a single program object. Unlike most shader languages, the program objects contain ''all'' programmable stages at once. Only one program can be bound for rendering at any one time, and it is illegal for a program object to omit any required stages entirely. Required stages are those for which there is no non-shader equivalent.
+
Shader objects are useless in that form, just as object files from compiled C programs are useless directly. Shader objects must be linked into a single program object. What makes GLSL's model unique is that multiple shader objects from different stages can be linked into a single program. So [[Vertex Shader]] and [[Fragment Shader]] can be linked into a single program.
  
{{legacy note|In compatibility mode, none of the stages are required, as fixed-functionality can always replicate them.}}
+
Note that if a shader stage is missing it's `main` function in the linker (ie: the program isn't given a shader object that defines `main` for that stage), then the stage is effectively not present in the program. It is possible to render with a program that only provides a [[Vertex Shader]], but you need to {{apifunc|glEnable|(GL_RASTERIZER_DISCARD)}} in order to get away with it.
 +
 
 +
Normally, you can only render with a single program, and thus a single program must combine every shader stage you wish to render with. However, if you have access to GL 4.1 or {{extref|separate_shader_objects}}, you may attach multiple programs, all with different shader stages, to a single program pipeline. This makes it easier to mix-and-match programs. See the [[#Program separation|Program separation section]] for more details.
  
 
== Terminology ==
 
== Terminology ==
Line 17: Line 19:
 
Because of GLSL's unique compilation model, GLSL uses unique terminology.
 
Because of GLSL's unique compilation model, GLSL uses unique 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.
+
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.
  
== Shader and program objects ==
+
=== Shader and program objects ===
  
 
Since GLSL's compilation model has 2 separate concepts, shaders and programs, there are 2 kinds of objects: shader objects and program objects. Shader objects represent compiled shaders, while program objects represent fully linked programs.
 
Since GLSL's compilation model has 2 separate concepts, shaders and programs, there are 2 kinds of objects: shader objects and program objects. Shader objects represent compiled shaders, while program objects represent fully linked programs.
  
Neither of these object types conforms to the standard [[OpenGL Objects]] paradigm. Rather than using a state-based methadology for most of their functions, they use a more object-based API. The compilation, linking, and state access functions for these objects all take the object as a parameter, rather than requiring that the object be bound to the context before use.
+
Neither of these object types conforms to the standard [[OpenGL Objects]] paradigm. Rather than using a state-based methodology for most of their functions, they use a more object-based API. The compilation, linking, and state access functions for these objects all take the object as a parameter, rather than requiring that the object be bound to the context before use.
  
 
== Object creation ==
 
== Object creation ==
  
Shader objects are created with a call to:
+
A shader object is created by a call to:
  
   GLuint [[GLAPI/glCreateShader|glCreateShader]](GLenum ''type'');
+
   GLuint {{apifunc|glCreateShader}}(GLenum {{param|type}});
  
The ''type'' field refers to the kind of shader object you wish to compile. A shader object can be of type GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, or GL_GEOMETRY_SHADER. Once created, this object can only ever be used for shaders of that particular type.
+
The {{param|type}} field refers to the kind of shader object you wish to compile. A shader object can be of type {{enum|GL_VERTEX_SHADER}}, {{enum|GL_FRAGMENT_SHADER}}, or {{enum|GL_GEOMETRY_SHADER}}. If OpenGL 4.0 or {{extref|tessellation_shader}} is available, then {{enum|GL_TESS_CONTROL_SHADER}} and {{enum|GL_TESS_EVALUATION_SHADER}} may be used. Once created, this object can only ever be used for shaders of that particular type.
  
{legacy note|In pre-OpenGL 3.1, you could ignore the glGen* functions, using any non-zero unsigned 32-bit integer as an object name. This was true for any OpenGL Object. However, because shader objects are not OpenGL Objects, you ''cannot'' do this, even in GL 2.0.}
+
{{legacy note|In pre-OpenGL 3.1, you could ignore the glGen* functions, using any non-zero unsigned 32-bit integer as an object name. This was true for any OpenGL Object. However, because shader objects are not OpenGL Objects, you ''cannot'' do this, even in GL 2.0.}}
  
 
They are deleted by calling:
 
They are deleted by calling:
  
   void [[GLAPI/glDeleteShader|glDeleteShader]](GLuint ''shader'');
+
   void {{apifunc|glDeleteShader}}(GLuint {{param|shader}});
  
 
Similarly, program objects are created and deleted with:
 
Similarly, program objects are created and deleted with:
  
   void [[GLAPI/glDeleteProgram|glDeleteProgram]](GLuint ''program'');
+
  GLuint {{apifunc|glCreateProgram}}();
 +
   void {{apifunc|glDeleteProgram}}(GLuint {{param|program}});
  
Note that the creation and deletion functions work one at a time, unlike those for regular OpenGL Objects.
+
{{apifunc|glCreateProgram}} does not take parameters.
 +
 
 +
Note that the creation and deletion functions only create one object at a time, unlike those for regular OpenGL Objects.
  
 
== Shader compiling ==
 
== Shader compiling ==
Line 49: Line 54:
 
Compiling a shader object is pretty simple. Before you can compile a shader, you must add strings to it. This is done with this command:
 
Compiling a shader object is pretty simple. Before you can compile a shader, you must add strings to it. This is done with this command:
  
   void [[GLAPI/glShaderSource|glShaderSource]](GLuint ''shader'', GLsizei ''count'', const char **''string'', const int *''length'');
+
   void {{apifunc|glShaderSource}}(GLuint {{param|shader}}, GLsizei {{param|count}}, const char **{{param|string}}, const int *{{param|length}});
  
The ''shader'' parameter is a previously created shader object. You can compile multiple strings in a single shader. This works exactly like appending these strings to one another, in the order given in the array. ''count'' tells how many strings are in the array, ''string'' is the array of strings to compile, and ''length'' is an array of lengths of those strings. ''length'' can be NULL; if it is, then all of the strings in ''string'' must be NULL-terminated. Otherwise, the lengths of the strings will be taken from the length value. If one of the elements in ''length'' is negative, then the corresponding string must be NULL-terminated.
+
The {{param|shader}} parameter is a previously created shader object. You can compile multiple strings in a single shader. This works exactly like appending these strings to one another, in the order given in the array. {{param|count}} tells how many strings are in the array, {{param|string}} is the array of strings to compile, and {{param|length}} is an array of lengths of those strings. {{param|length}} can be NULL; if it is, then all of the strings in {{param|string}} must be NULL-terminated. Otherwise, the lengths of the strings will be taken from the length value. If one of the elements in {{param|length}} is negative, then the corresponding string must be NULL-terminated.
  
 
Calling this function will also undo any previous calls to this function for this command. So calling this multiple times will not add multiple strings; that's why the function intrinsically takes multiple strings.
 
Calling this function will also undo any previous calls to this function for this command. So calling this multiple times will not add multiple strings; that's why the function intrinsically takes multiple strings.
Line 59: Line 64:
 
Once strings have been set, you can then compile the shader:
 
Once strings have been set, you can then compile the shader:
  
   void [[GLAPI/glCompileShader|glCompileShader]](GLuint ''shader'');
+
   void {{apifunc|glCompileShader}}(GLuint {{param|shader}});
  
 
This does not return a value; you can query the success or failure of the compilation via glGetShaderiv. See the section on [[#Error handling]] for this.
 
This does not return a value; you can query the success or failure of the compilation via glGetShaderiv. See the section on [[#Error handling]] for this.
Line 73: Line 78:
 
In order to link a program, you must ''attach'' one or more compiled shader objects to the program. This is done with this API:
 
In order to link a program, you must ''attach'' one or more compiled shader objects to the program. This is done with this API:
  
   void [[GLAPI/glAttachShader|glAttachShader]](GLuint ''program'', GLuint ''shader'');
+
   void {{apifunc|glAttachShader}}(GLuint {{param|program}}, GLuint {{param|shader}});
  
This will cause the shader object ''shader'' to become attached to the program object ''program''. A shader object can be attached to any number of program objects. The shader object, due to being attached to the program object, will continue to exist even if you delete the shader object. It will only be deleted by the system when it is no longer attached to any program object (and when the user has asked to delete it, of course). Even so, it is not a good idea to refer to shader objects after deleting them.
+
This will cause the shader object {{param|shader}} to become attached to the program object {{param|program}}. A shader object can be attached to any number of program objects. The shader object, due to being attached to the program object, will continue to exist even if you delete the shader object. It will only be deleted by the system when it is no longer attached to any program object (and when the user has asked to delete it, of course). Even so, it is not a good idea to refer to shader objects after deleting them.
  
You do not have to explicitly detach shader objects, even after linking the program. However, if you wish to do so, you may use this function:
+
=== Pre-link setup ===
  
  void [[GLAPI/glDetachShader|glDetachShader]](GLuint ''program'', GLuint ''shader'');
+
There are a number of operations that may need to be performed on programs before linking.
  
The next step in linking the program is to provide attribute indices for any vertex attributes. This is only important if you have a vertex shader as part of the program.
+
[[Vertex Attribute]]s for a [[Vertex Shader]] (if present in the program object) can be manually assigned an attribute index. Obviously, if no vertex shader is in the program, you do not need to assign attributes manually. Note that it is still best to [[GLSL_Type_Qualifiers#Vertex_shader_attribute_index|assign them explicitly in the shader]], where possible.
 
+
This step is also optional. If you wish, OpenGL can automatically assign your vertex attributes to an index. However, since you must know this index in order to set up your [[Vertex Array Objects|VAO]] correctly, and you will likely want to be able to mix and match VAOs and programs as much as you want, it is best to pick your own vertex attribute indices.
+
  
 
To do this, call this API before linking the program:
 
To do this, call this API before linking the program:
  
   void [[GLAPI/glBindAttribLocation|glBindAttribLocation]](GLuint ''program'', GLuint ''index'', const char *''name'');
+
   void {{apifunc|glBindAttribLocation}}(GLuint {{param|program}}, GLuint {{param|index}}, const char *{{param|name}});
  
The ''index'' is the attribute value you want to assign, and ''name'' is the string name of the attribute in the vertex shader that you want to use. The binding this function creates only takes effect when the program is linked. The attribute ''name'' does not have to actually be in the linked program; this allows you to set up a global mapping of names to indices and simply always use them for every program you create.
+
The {{param|index}} is the attribute value you want to assign, and {{param|name}} is the string name of the attribute in the vertex shader that you want to use. The binding this function creates only takes effect when the program is linked. The attribute {{param|name}} does not have to actually be in the linked program; this allows you to set up a global mapping of names to indices and simply always use them for every program you create.
  
If one is rendering to a framebuffer (as opposed to a vertex buffer through transform feedback), then the output values must be mapped to the current framebuffer's draw buffer indices. If the fragment shader only writes to one user-defined output, then this output will be automatically bound to output index 0. Otherwise, the output indices will be automatically generated, just as for vertex shader inputs.
+
If one is using a [[Fragment Shader]], the output values from the [[Fragment Shader]] must be mapped to the current [[Framebuffer Object#Multiple Render Targets|framebuffer's draw buffer indices]]. If the fragment shader only writes to one user-defined output, then this output will be automatically bound to output buffer index 0 (with dual-source index 0, when considering [[Blending#Dual Source Blending|dual-source blending]]). Otherwise, the output indices will be automatically generated, just as for vertex shader inputs.
  
Automatic generation of output indices is generally just fine for writing to a single output buffer. The generated index is 0, which is generally what you want. However, when dealing with multiple output buffers, automatic generation is less useful than for attribute indices. That is because you are far more likely to need to use multiple program with the same framebuffer, and the changes made by glDrawBuffers is part of the framebuffer's state. If you do not wish to change this parameter for every use of a program, then you are advised to manually assign output indices for all of your programs.
+
As with vertex attributes, fragment shader output indices can be manually assigned from within the shader, and this is the preferred way to handle them. They can also be automatically generated for any outputs that are not manually assigned, though this is highly unhelpful for multiple output buffers. This is because you are far more likely to need to use multiple program with the same framebuffer, and the changes made by {{apifunc|glDrawBuffers}} is part of the framebuffer's state and can affect FBO completeness. If you do not wish to change the draw buffers every time you use a new program, then you are advised to manually assign output indices for all of your programs.
  
To do this, call this API before linking:
+
To do this without explicitly providing it in the shader, call this API before linking:
  
   void [[GLAPI/glBindFragDataLocation|glBindFragDataLocation]](GLuint ''program'', GLuint ''colorNumber'', const char *''name'');
+
   void {{apifunc|glBindFragDataLocation}}(GLuint {{param|program}}, GLuint {{param|colorNumber}}, const char *{{param|name}});
  
The ''colorNumber'' is the index into the [[Framebuffer Object|glDrawBuffers]] list that the output named ''name'' will be written into.
+
The {{param|colorNumber}} is the index into the {{apifunc|glDrawBuffers}} list that the output named {{param|name}} will be written into.
  
If you are instead intending to use this program for [[Transform Feedback|transform feedback]], then you must tell the program which outputs from the last shader stage should be written to the buffer objects.
+
For [[Blending#Dual Source Blending|dual-source blending]], you need to be able to associate a buffer index and a dual-source index with the output. This is done with this function:
 +
 
 +
  void {{apifunc|glBindFragDataLocationIndexed}}(GLuint {{param|program}}, GLuint {{param|colorNumber}}, GLuint {{param|index}}, const char *{{param|name}});
 +
 
 +
The {{param|index}} is either 0 or 1, defining which dual-source index is being assigned to the output.
 +
 
 +
If you are intending to use this program for [[Transform Feedback]], then you must tell the program which outputs from the last shader stage before [[Vertex Post-Processing]] should be written to the transform feedback buffer objects.
  
 
To do this, call this API before linking:
 
To do this, call this API before linking:
  
   void [[GLAPI/glTransformFeedbackVaryings|glTransformFeedbackVaryings]](GLuint ''program'', GLsizei ''count'', const char **''varyings'', GLenum ''bufferMode'');
+
   void {{apifunc|glTransformFeedbackVaryings}}(GLuint {{param|program}}, GLsizei {{param|count}}, const char **{{param|varyings}}, GLenum {{param|bufferMode}});
 +
 
 +
The {{param|varyings}} is a string array of {{param|count}} elements. These named outputs, in order, will be written to the buffer. The {{param|bufferMode}} says whether the written attributes will be interleaved or written separately to the buffer.
  
The ''varyings'' is a string array of ''count'' elements. These named outputs, in order, will be written to the buffer. The ''bufferMode'' says whether the written attributes will be interleaved or written separately to the buffer.
+
=== Linking ===
  
 
Once all of this has been set up as the user wishes, then you may call:
 
Once all of this has been set up as the user wishes, then you may call:
  
   void [[GLAPI/glLinkProgram|glLinkProgram]](GLuint ''program'');
+
   void {{apifunc|glLinkProgram}}(GLuint {{param|program}});
  
 
This will link the program.
 
This will link the program.
  
=== Error handling ===
+
You do not have to explicitly detach shader objects, even after linking the program. However, it is a good idea to do so once linking is complete, as otherwise the program object will keep its attached shader objects alive when you try to delete them. Shader objects can be detached with this function:
 +
 
 +
  void {{apifunc|glDetachShader}}(GLuint {{param|program}}, GLuint {{param|shader}});
 +
 
 +
If the shader no longer needs to be used, it can be deleted.
 +
 
 +
== Error handling ==
  
 
Compiling and linking can cause errors. Unlike most [[OpenGL Error|OpenGL errors]] however, these errors are delivered in the form of text.
 
Compiling and linking can cause errors. Unlike most [[OpenGL Error|OpenGL errors]] however, these errors are delivered in the form of text.
  
To check to see if a shader successfully compiled, call <code>glGetShaderiv(''shader'', GL_COMPILE_STATUS, &bDidCompile)</code>. The integer pointer will be filled with GL_TRUE if the compilation was successful and GL_FALSE if it was not. Similarly, to check to see if a program linked, call <code>glGetProgramiv(''program'', GL_LINK_STATUS, &bDidLink)</code>.
+
To check to see if a shader successfully compiled, call {{apifunc|glGetShader|iv(''shader'', GL_COMPILE_STATUS, &bDidCompile)}}. The integer pointer will be filled with {{enum|GL_TRUE}} if the compilation was successful and {{enum|GL_FALSE}} if it was not. Similarly, to check to see if a program linked, call {{apifunc|glGetProgram|iv(''program'', GL_LINK_STATUS, &bDidLink)}}.
  
Compiling and linking, whether successful or not, will generate a textual log. The log will contain warnings and errors, as appropriate to the shader and program in question. The length of the log can be queried with glGetShader/Programiv with GL_INFO_LOG_LENGTH as the parameter. The logs themselves can be queried with this function:
+
Compiling and linking, whether successful or not, will generate a textual log. The log will contain warnings and errors, as appropriate to the shader and program in question. The length of the log can be queried with {{apifunc|glGetShader}}/{{apifunc|glGetProgram}} with {{enum|GL_INFO_LOG_LENGTH}} as the parameter. The logs themselves can be queried with this function:
  
void [[GLAPI/glGetShaderInfoLog|glGetShaderInfoLog]]( GLuint ''shader'', GLsizei ''bufSize'', GLsizei *''length'', char *''infoLog'' );
+
void {{apifunc|glGetShaderInfoLog}}( GLuint {{param|shader}}, GLsizei {{param|bufSize}}, GLsizei *{{param|length}}, char *{{param|infoLog}} );
void [[GLAPI/glGetProgramInfoLog|glGetProgramInfoLog]]( GLuint ''program'', GLsizei ''bufSize'', GLsizei *''length'', char *''infoLog'' );
+
void {{apifunc|glGetProgramInfoLog}}( GLuint {{param|program}}, GLsizei {{param|bufSize}}, GLsizei *{{param|length}}, char *{{param|infoLog}} );
  
This will cause the ''infoLog'' buffer (of size ''bufSize'') to be filled in with the log. If ''length'' is non-NULL, it will be filled in with the number of characters written to ''infoLog''.
+
This will cause the {{param|infoLog}} buffer (of size {{param|bufSize}}, including space for the null terminator) to be filled in with the log. If {{param|length}} is non-NULL, it will be filled in with the number of characters written to {{param|infoLog}}.
  
 
== Program usage ==
 
== Program usage ==
Line 134: Line 151:
 
To bind a program to the context for rendering, call:
 
To bind a program to the context for rendering, call:
  
   void [[GLAPI/glUseProgram|glUseProgram]](GLuint ''program'');
+
   void {{apifunc|glUseProgram}}(GLuint {{param|program}});
  
As with the usual glBind* calls, this will cause ''program'' to become the actively bound program and cause the previously bound program to be unbound. And just as with the usual glBind* calls, binding the 0 program object will cause the program to be unbound.
+
As with the usual glBind* calls, this will cause {{param|program}} to become the actively bound program and cause the previously bound program to be unbound. And just as with the usual glBind* calls, binding the 0 program object will cause the program to be unbound. Rendering without a program (or [[#Program separation|program pipeline]] will cause errors.
  
Program objects store the state of [[GLSL Uniforms|GLSL Uniform values]]. These can be queried and set through program objects.
+
Program objects store the state of [[GLSL Uniform|GLSL Uniform values]]. These values can be retrieved and set as normal.
  
You can retrieve information about the attribute and fragment data location bindings as well.
+
== Program introspection ==
 +
{{main|Program Introspection}}
  
Like uniforms, attributes can be active or inactive. Attributes that are unused are inactive; they do not have a binding. The number of active attributes in a program can be retrieved with <code>[[GLAPI/glGetProgram|glGetProgramiv]]</code> with GL_ACTIVE_ATTRIBUTES.
+
You can retrieve information about the uniforms, attribute, and fragment data stored in a program. This can be used to query for locations, but it can also be used to find general information about the user-facing interfaces within a program.
 
+
To retrieve information about an attribute, call this function:
+
 
+
  void [[GLAPI/glGetActiveAttrib|glGetActiveAttrib]]( GLuint ''program'', GLuint ''index'', GLsizei ''bufSize'', GLsizei *''length'', GLint *''size'', GLenum *''type'', char *''name'' );
+
 
+
The ''index'' is a number on the half-open range [0, GL_ACTIVE_ATTRIBUTES); it represents a particular active attribute. ''name'' will be filled in with the name of the attribute; ''bufSize'' is the size of this character array. If ''length'' is not NULL, it will be filled in with the number of characters written to ''name''. The ''size'' will be filled with the number of elements in the attribute array, if the attribute is an array type. Otherwise, it will be set to 1. The ''type'' will be set to the OpenGL enumeration for the GLSL type of the attribute.
+
 
+
To get the attribute location (the one used by [[GLAPI/glVertexAttribPointer|glVertexAttribPointer]], not the ''index'' field used above), we use this function:
+
 
+
  GLint [[GLAPI/glGetAttribLocation|glGetAttribLocation]]( GLuint ''program'', const char *''name'' );
+
 
+
If ''name'' is not an active attribute in ''program'', the function will return -1.
+
 
+
Similarly, to get the fragment data location we use this function:
+
 
+
  GLint [[GLAPI/glGetFragDataLocation|glGetFragDataLocation]]( GLuint ''program'', const char *''name'' );
+
 
+
Again, if ''name'' is not a fragment data location in ''program'', the function returns -1.
+
  
 
== Program separation ==
 
== Program separation ==
Line 172: Line 172:
  
 
The above paradigm is functional, but with the increase in the number of shader stages, the combinatorial explosion of different combinations of shaders is very great. Therefore, it is possible to compile and link program objects into individual shader stages, and then dynamically combine them when necessary.
 
The above paradigm is functional, but with the increase in the number of shader stages, the combinatorial explosion of different combinations of shaders is very great. Therefore, it is possible to compile and link program objects into individual shader stages, and then dynamically combine them when necessary.
 +
 +
== Reference ==
 +
 +
* [[:Category:Core API Ref Shader Program Creation]]: Reference manual for all core OpenGL functions that create shaders, programs, and program pipeline objects.
 +
* [[:Category:Core API Ref Shader Program Query]]: Reference manual for all core OpenGL functions that get information from shaders and programs. These are used to investigate attributes, uniforms, etc.
 +
* [[:Category:Core API Ref Shader Program Usage and State‏‎]]: Reference manual for all core OpenGL functions that set state on programs and program pipeline objects, as well as bind and use them.
  
  

Revision as of 00:46, 5 October 2012

A GLSL Object is an object in the OpenGL API that encapsulates the compiled or linked programs that execute portions of the OpenGL Pipeline. These objects represent code written in the OpenGL Shading Language (GLSL). Though they are called "objects", they do not fit within the OpenGL Object paradigm.

GLSL compilation model

GLSL is quite unique among shading languages due to its compilation model. Most shading languages use a simpler, one-stage model: you give it a string representing a shader for one of the shader stages, and it gives you a shader object that you can bind to the context and render with.

GLSL uses a more complicated model based on the compilation of C programs. In C, a compilation unit, typically a single source file that may include several external header files, is compiled into an object file. A number of object files are then linked into a single program.

GLSL operates in a similar fashion. A set of source files, given as a series of strings, are compiled into a shader object. This is the analog of an object file. Unlike typical shading languages, there is no requirement that this shader object represent the full code for a shader stage. The only limitation is that it can only contain code that is appropriate for a single, specific shader stage.

Shader objects are useless in that form, just as object files from compiled C programs are useless directly. Shader objects must be linked into a single program object. What makes GLSL's model unique is that multiple shader objects from different stages can be linked into a single program. So Vertex Shader and Fragment Shader can be linked into a single program.

Note that if a shader stage is missing it's `main` function in the linker (ie: the program isn't given a shader object that defines `main` for that stage), then the stage is effectively not present in the program. It is possible to render with a program that only provides a Vertex Shader, but you need to glEnable(GL_RASTERIZER_DISCARD) in order to get away with it.

Normally, you can only render with a single program, and thus a single program must combine every shader stage you wish to render with. However, if you have access to GL 4.1 or ARB_separate_shader_objects, you may attach multiple programs, all with different shader stages, to a single program pipeline. This makes it easier to mix-and-match programs. See the Program separation section for more details.

Terminology

Because of GLSL's unique compilation model, GLSL uses unique 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.

Shader and program objects

Since GLSL's compilation model has 2 separate concepts, shaders and programs, there are 2 kinds of objects: shader objects and program objects. Shader objects represent compiled shaders, while program objects represent fully linked programs.

Neither of these object types conforms to the standard OpenGL Objects paradigm. Rather than using a state-based methodology for most of their functions, they use a more object-based API. The compilation, linking, and state access functions for these objects all take the object as a parameter, rather than requiring that the object be bound to the context before use.

Object creation

A shader object is created by a call to:

 GLuint glCreateShader(GLenum type​);

The type​ field refers to the kind of shader object you wish to compile. A shader object can be of type GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, or GL_GEOMETRY_SHADER. If OpenGL 4.0 or ARB_tessellation_shader is available, then GL_TESS_CONTROL_SHADER and GL_TESS_EVALUATION_SHADER may be used. Once created, this object can only ever be used for shaders of that particular type.

Legacy Note: In pre-OpenGL 3.1, you could ignore the glGen* functions, using any non-zero unsigned 32-bit integer as an object name. This was true for any OpenGL Object. However, because shader objects are not OpenGL Objects, you cannot do this, even in GL 2.0.

They are deleted by calling:

 void glDeleteShader(GLuint shader​);

Similarly, program objects are created and deleted with:

 GLuint glCreateProgram();
 void glDeleteProgram(GLuint program​);

glCreateProgram does not take parameters.

Note that the creation and deletion functions only create one object at a time, unlike those for regular OpenGL Objects.

Shader compiling

Compiling a shader object is pretty simple. Before you can compile a shader, you must add strings to it. This is done with this command:

 void glShaderSource(GLuint shader​, GLsizei count​, const char **string​, const int *length​);

The shader​ parameter is a previously created shader object. You can compile multiple strings in a single shader. This works exactly like appending these strings to one another, in the order given in the array. count​ tells how many strings are in the array, string​ is the array of strings to compile, and length​ is an array of lengths of those strings. length​ can be NULL; if it is, then all of the strings in string​ must be NULL-terminated. Otherwise, the lengths of the strings will be taken from the length value. If one of the elements in length​ is negative, then the corresponding string must be NULL-terminated.

Calling this function will also undo any previous calls to this function for this command. So calling this multiple times will not add multiple strings; that's why the function intrinsically takes multiple strings.

Note that, like any other OpenGL function that takes pointers, the information in those pointers is copied to the OpenGL context before the function returns. Therefore, you may free this memory afterward.

Once strings have been set, you can then compile the shader:

 void glCompileShader(GLuint shader​);

This does not return a value; you can query the success or failure of the compilation via glGetShaderiv. See the section on #Error handling for this.

A shader object, once it has successfully compiled, can be compiled with a different set of strings. All you need to do is call glShaderSource and glCompileShader again. This is not advisable, however. It is preferable to simply delete the shader object and build a new one, as recompiling the shader will likely not have the effect you intend.

For example, if you have a program and you attach a shader to it, recompiling the shader with new code will not update the program. This is exactly like it is for object files on the disk; it doesn't matter that you change a .o file once you've already used it to generate the executable. You must re-link the executable manually in order for the changes to take effect.

Program linking

Linking a program is not as simple as compiling a shader. The linking process involves more than just taking a collection of compiled shader objects and building a program from them. Though that is the first step.

In order to link a program, you must attach one or more compiled shader objects to the program. This is done with this API:

 void glAttachShader(GLuint program​, GLuint shader​);

This will cause the shader object shader​ to become attached to the program object program​. A shader object can be attached to any number of program objects. The shader object, due to being attached to the program object, will continue to exist even if you delete the shader object. It will only be deleted by the system when it is no longer attached to any program object (and when the user has asked to delete it, of course). Even so, it is not a good idea to refer to shader objects after deleting them.

Pre-link setup

There are a number of operations that may need to be performed on programs before linking.

Vertex Attributes for a Vertex Shader (if present in the program object) can be manually assigned an attribute index. Obviously, if no vertex shader is in the program, you do not need to assign attributes manually. Note that it is still best to assign them explicitly in the shader, where possible.

To do this, call this API before linking the program:

 void glBindAttribLocation(GLuint program​, GLuint index​, const char *name​);

The index​ is the attribute value you want to assign, and name​ is the string name of the attribute in the vertex shader that you want to use. The binding this function creates only takes effect when the program is linked. The attribute name​ does not have to actually be in the linked program; this allows you to set up a global mapping of names to indices and simply always use them for every program you create.

If one is using a Fragment Shader, the output values from the Fragment Shader must be mapped to the current framebuffer's draw buffer indices. If the fragment shader only writes to one user-defined output, then this output will be automatically bound to output buffer index 0 (with dual-source index 0, when considering dual-source blending). Otherwise, the output indices will be automatically generated, just as for vertex shader inputs.

As with vertex attributes, fragment shader output indices can be manually assigned from within the shader, and this is the preferred way to handle them. They can also be automatically generated for any outputs that are not manually assigned, though this is highly unhelpful for multiple output buffers. This is because you are far more likely to need to use multiple program with the same framebuffer, and the changes made by glDrawBuffers is part of the framebuffer's state and can affect FBO completeness. If you do not wish to change the draw buffers every time you use a new program, then you are advised to manually assign output indices for all of your programs.

To do this without explicitly providing it in the shader, call this API before linking:

 void glBindFragDataLocation(GLuint program​, GLuint colorNumber​, const char *name​);

The colorNumber​ is the index into the glDrawBuffers list that the output named name​ will be written into.

For dual-source blending, you need to be able to associate a buffer index and a dual-source index with the output. This is done with this function:

 void glBindFragDataLocationIndexed(GLuint program​, GLuint colorNumber​, GLuint index​, const char *name​);

The index​ is either 0 or 1, defining which dual-source index is being assigned to the output.

If you are intending to use this program for Transform Feedback, then you must tell the program which outputs from the last shader stage before Vertex Post-Processing should be written to the transform feedback buffer objects.

To do this, call this API before linking:

 void glTransformFeedbackVaryings(GLuint program​, GLsizei count​, const char **varyings​, GLenum bufferMode​);

The varyings​ is a string array of count​ elements. These named outputs, in order, will be written to the buffer. The bufferMode​ says whether the written attributes will be interleaved or written separately to the buffer.

Linking

Once all of this has been set up as the user wishes, then you may call:

 void glLinkProgram(GLuint program​);

This will link the program.

You do not have to explicitly detach shader objects, even after linking the program. However, it is a good idea to do so once linking is complete, as otherwise the program object will keep its attached shader objects alive when you try to delete them. Shader objects can be detached with this function:

 void glDetachShader(GLuint program​, GLuint shader​);

If the shader no longer needs to be used, it can be deleted.

Error handling

Compiling and linking can cause errors. Unlike most OpenGL errors however, these errors are delivered in the form of text.

To check to see if a shader successfully compiled, call glGetShaderiv(shader, GL_COMPILE_STATUS, &bDidCompile). The integer pointer will be filled with GL_TRUE if the compilation was successful and GL_FALSE if it was not. Similarly, to check to see if a program linked, call glGetProgramiv(program, GL_LINK_STATUS, &bDidLink).

Compiling and linking, whether successful or not, will generate a textual log. The log will contain warnings and errors, as appropriate to the shader and program in question. The length of the log can be queried with glGetShader/glGetProgram with GL_INFO_LOG_LENGTH as the parameter. The logs themselves can be queried with this function:

void glGetShaderInfoLog( GLuint shader​, GLsizei bufSize​, GLsizei *length​, char *infoLog​ ); void glGetProgramInfoLog( GLuint program​, GLsizei bufSize​, GLsizei *length​, char *infoLog​ );

This will cause the infoLog​ buffer (of size bufSize​, including space for the null terminator) to be filled in with the log. If length​ is non-NULL, it will be filled in with the number of characters written to infoLog​.

Program usage

The only thing you can use shader objects for is to make programs. Program objects however, have many uses.

To bind a program to the context for rendering, call:

 void glUseProgram(GLuint program​);

As with the usual glBind* calls, this will cause program​ to become the actively bound program and cause the previously bound program to be unbound. And just as with the usual glBind* calls, binding the 0 program object will cause the program to be unbound. Rendering without a program (or program pipeline will cause errors.

Program objects store the state of GLSL Uniform values. These values can be retrieved and set as normal.

Program introspection

You can retrieve information about the uniforms, attribute, and fragment data stored in a program. This can be used to query for locations, but it can also be used to find general information about the user-facing interfaces within a program.

Program separation

Program Separation
Core in version 4.5
Core since version 4.1
ARB extension GL_ARB_separate_shader_objects

The above paradigm is functional, but with the increase in the number of shader stages, the combinatorial explosion of different combinations of shaders is very great. Therefore, it is possible to compile and link program objects into individual shader stages, and then dynamically combine them when necessary.

Reference