Uniform Variables
Prev: Comm. OpenGL => Shaders | Next: Attribute Variables |
A uniform variable can have its value changed by primitive only, i.e., its value can’t be changed between a glBegin / glEnd pair. This implies that it can’t be used for vertices attributes. Look for the subsection on attribute variables if that is what you’re looking for. Uniform variables are suitable for values that remain constant along a primitive, frame, or even the whole scene. Uniform variables can be read (but not written) in both vertex and fragment shaders.
The first thing you have to do is to get the memory location of the variable. Note that this information is only available after you link the program. Note: with some drivers you may be required to be using the program, i.e. you’ll have to call (OpenGL 2.0) glUseProgram or (ARB extensions) glUseProgramObjectARB before attempting to get the location (it happens with my laptop ATI graphics card).
The syntax for OpenGL 2.0 and ARB extensions is very similar when dealing with variables. Basically just drop the “ARB” from the name of the function if moving from an ARB extension application to an OpenGL 2.0 application.
The function to retrieve the location of an uniform variable given its name, as defined in the shader, is (OpenGL 2.0 syntax):
GLint glGetUniformLocation(GLuint program, const char *name);
Parameters:
- program – the handler to the program
- name – the name of the variable.
And using ARB extensions:
GLint glGetUniformLocationARB(GLhandleARB program, const char *name);
Parameters:
- program – the handler to the program
- name – the name of the variable.
The return value is the location of the variable, which can then be used to assign values to it. A family of functions is provided for setting uniform variables, its usage being dependent on the data type of the variable. A set of functions is defined for setting float values as (OpenGL 2.0 notation):
void glUniform1f(GLint location, GLfloat v0);
void glUniform2f(GLint location, GLfloat v0, GLfloat v1);
void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
or
GLint glUniform{1,2,3,4}fv(GLint location, GLsizei count, GLfloat *v);
Parameters:
- location – the previously queried location.
- v0,v1,v2,v3 – float values.
- count – the number of elements in the array
- v – an array of floats.
Using the ARB extensions:
void glUniform1fARB(GLint location, GLfloat v0);
void glUniform2fARB(GLint location, GLfloat v0, GLfloat v1);
void glUniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
void glUniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
or
GLint glUniform{1,2,3,4}fvARB(GLint location, GLsizei count, GLfloat *v);
Parameters:
- location – the previously queried location.
- v0,v1,v2,v3 – float values.
- count – the number of elements in the array
- v – an array of floats.
A similar set of function is available for data type integer, where “f” is replaced by “i”. There are no functions specifically for bools, or boolean vectors. Just use the functions available for float or integer and set zero for false, and anything else for true. In case you have an array of uniform variables the vector version should be used.
For sampler variables, use the functions (OpenGL 2.0 notation) glUniform1i, or glUniform1iv if setting an array of samplers.
When using the ARB extensions use the functions glUniform1iARB, or glUniform1ivARB if setting an array of samplers.
Matrices are also an available data type in GLSL, and a set of functions is also provided for this data type:
GLint glUniformMatrix{2,3,4}fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *v);
Parameters:
- location – the previously queried location.
- count – the number of matrices. 1 if a single matrix is being set, or n for an array of n matrices.
- transpose – wheter to transpose the matrix values. A value of 1 indicates that the matrix values are specified in row major order, zero is column major order
- v – an array of floats.
And using the ARB extensions:
GLint glUniformMatrix{2,3,4}fvARB(GLint location, GLsizei count, GLboolean transpose, GLfloat *v);
Parameters:
- location – the previously queried location.
- count – the number of matrices. 1 if a single matrix is being set, or n for an array of n matrices.
- transpose – wheter to transpose the matrix values. A value of 1 indicates that the matrix values are specified in row major order, zero is column major order
- v – an array of floats.
An important note to close this subsection, and before some source code is presented: the values that are set with these functions will keep their values until the program is linked again. Once a new link process is performed all values will be reset to zero.
And now to some source code. Assume that a shader with the following variables is being used:
uniform float specIntensity; uniform vec4 specColor; uniform float t[2]; uniform vec4 colors[3];
In an OpenGL 2.0 application, the code for setting the variables could be:
GLint loc1,loc2,loc3,loc4;
float specIntensity = 0.98;
float sc[4] = {0.8,0.8,0.8,1.0};
float threshold[2] = {0.5,0.25};
float colors[12] = {0.4,0.4,0.8,1.0,
0.2,0.2,0.4,1.0,
0.1,0.1,0.1,1.0};
loc1 = glGetUniformLocation(p,"specIntensity");
glUniform1f(loc1,specIntensity);
loc2 = glGetUniformLocation(p,"specColor");
glUniform4fv(loc2,1,sc);
loc3 = glGetUniformLocation(p,"t");
glUniform1fv(loc3,2,threshold);
loc4 = glGetUniformLocation(p,"colors");
glUniform4fv(loc4,3,colors);
If the application uses ARB extensions then the code could be as follows:
GLint loc1,loc2,loc3,loc4;
float specIntensity = 0.98;
float sc[4] = {0.8,0.8,0.8,1.0};
float threshold[2] = {0.5,0.25};
float colors[12] = {0.4,0.4,0.8,1.0,
0.2,0.2,0.4,1.0,
0.1,0.1,0.1,1.0};
loc1 = glGetUniformLocationARB(p,"specIntensity");
glUniform1fARB(loc1,specIntensity);
loc2 = glGetUniformLocationARB(p,"specColor");
glUniform4fvARB(loc2,1,sc);
loc3 = glGetUniformLocationARB(p,"t");
glUniform1fvARB(loc3,2,threshold);
loc4 = glGetUniformLocationARB(p,"colors");
glUniform4fvARB(loc4,3,colors);
A working example, with source code, is available: OpenGL 2.0 syntax or ARB syntax
Notice the difference between setting an array of values, as it is the case of t or colors, and setting a vector with 4 values, as the specColor. The count parameter (middle parameter of glGetUniform{1,2,3,4}fv) specifies the number of array elements as declared in the shader, not as declared in the OpenGL application. So although specColor contains 4 values, the count of the function glUniform4fv parameter is set to 1, because it is only one vector. An alternative for setting the specColor variable could be:
loc2 = glGetUniformLocation(p,"specColor");
glUniform4f(loc2,sc[0],sc[1],sc[2],sc[3]);
Yet another possibility provided by GLSL is to get the location of a variable inside an array. For instance, it is possible to get the location of t[1]. The following snippet of code shows this approach to set the t array elements.
loct0 = glGetUniformLocation(p,"t[0]");
glUniform1f(loct0,threshold[0]);
loct1 = glGetUniformLocation(p,"t[1]");
glUniform1f(loct1,threshold[1]);
Notice how the variable is specified in glGetUniformLocation using square brackets.
The ARB extensions variant to the code above is very similar (just add “ARB” to the functions names) so it has been omitted in here.
Prev: Comm. OpenGL => Shaders | Next: Attribute Variables |
9 Responses to “Uniform Variables”
Leave a Reply Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
Thank you so much for these amazing tutorials!
I’ve gone through so much trash on the internet until i found this website.
Your tutorials are ridiculously nice to follow, keep it up 🙂
I can’t thank you enough 😛
Greetings and all the best, take care
Thanks for your kind words.
Some “hanule(r)” -> “handle(r)” here to.
Fixed. Many thanks 🙂
A possible typo in the paragraph “Notice the difference…”:
shouldn’t “glGetUniform{1,2,3,4}fv” be “glUniform{1,2,3,4}fv”?
Many thanks for the tutorials! 🙂
I got an error from toon3.frag.
the log shows
gl_FragColor syntax error parse error.
What does it mean ? and What should I do?
It’s supernatural. I got an error from toon3.frag from the zip file of this section. So I created a new fragment shader and copy all text from toon3.frag to it.
Surprisingly, it works now.
crazy me 🙁
hello, i understand how to set the count values according to the shader in glUniform, but why is the glUniform{1,2,3,4}, set to glUniform1fv for loc3, and glUniform4fv for loc4?
I guess a restatement of my question is: according to what do I set the number ‘X’ in glUniformXfv?
thank you this site is tremendous
The number you refer to is related to the number of components a uniform has. For instance t is an array of floats, hence each element of the array has one float, where as colors is an array of vec4 where each element of the array has four floats.