 |
|
GLSL Tutorial
Index
Introduction
The Graphics Pipeline Pipeline Overview Vertex Processor Fragment Processor
OpenGL Setup for GLSL Overview Creating a Shader Creating a Program Source Code Trouble Shooting: the InfoLog Cleaning Up
Comm. OpenGL=> GLSL Comm. Introduction Uniform Variables Attribute Variables
Shader Basics Data Types and Variables Statments and Functions Varying Variables
Shader Examples Shader Examples List
GLSL Hello World
Color Shader
Flatten Shader
Toon Shader Toon Shader - Version I Toon Shader - Version II Toon Shader - Version III
Lighting OpenGL Directional Light I OpenGL Directional Light II Directional Light per Pixel Point Light Per Pixel Spot Light Per Pixel
Simple Texture Combine Texture + Fragment Multitexturing
Notes The gl_NormalMatrix Normalization Issues
OpenGLTutorials @ Lighthouse3d.com
Led Shader
View Frustum Culling
GLSL Tutorial
Maths Tutorial
Billboarding Tutorial
Picking Tutorial
Terrain Tutorial
Display Lists Tutorial
GLUT Tutorial
|
|
 |
|
GLSL Tutorial
OpenGL Setup for GLSL - Uniform 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. BSasically 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 extenstions 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 the square brackets.
The ARB extensions variant to the code above is very similar (just add "ARB" to the functions names) so it has been ommited in here.
|