The uniform variables contain the data values that are global. They are shared by all vertices and fragments in the vertex and fragment shaders. Generally, some information that is not specific to the per-vertex is treated in the form of uniform variables. The uniform variable could exist in both the vertex and fragment shaders.
The vertex shader we programmed in the Programming shaders in OpenGL ES shading language 3.0 recipe contains a uniform variable RadianAngle
. This variable is used to rotate the rendered triangle:
// Uniform variable for rotating triangle uniform float RadianAngle;
This variable will be updated on the client side (CPU) and send to the shader at server side (GPU) using special OpenGL ES 3.0 APIs. Similar to per-vertex attributes for uniform variables, we need to query and bind data in order to make it available in the shader.
Follow these steps to send data to a shader using uniform variables:
Declare a global variable in
NativeTemplate.cpp
to store the queried attribute location IDs ofradianAngle
:GLuint radianAngle;
Query the uniform variable location using the
glGetUniformLocation
API:radianAngle=glGetUniformLocation(programID,"RadianAngle");
This API will return a value greater than or equal to
0
to ensure that a uniform variable with the given name exists.Syntax:
GLint glGetUniformLocation(GLuint program,const GLchar *name)
Variable
Description
program
This is the handle of a successfully linked OpenGL ES program
name
This is the name of the uniform variable in the shader source program
Send the updated radian value to the shader using the
glUniform1f
API:float degree = 0; // Global degree variable float radian; // Global radian variable // Update angle and convert it into radian radian = degree++/57.2957795; // Send updated data in the vertex shader uniform glUniform1f(radianAngle, radian);
There are many variants of the
glUniform
API.Syntax:
void glUniform1f(GLint location, GLfloat v0);
Variable
Description
location
This is the index of the uniform variable in the shader
v0
This is the data value of type float that needs to be sent
Note
For more information on other variants, refer to OpenGL ES 3.0 Reference Pages at http://www.khronos.org/opengles/sdk/docs/man3/.
Use a general form of 2D rotation to apply on the entire incoming vertex coordinates:
. . . . uniform float RadianAngle; mat2 rotation = mat2(cos(RadianAngle),sin(RadianAngle), -sin(RadianAngle),cos(RadianAngle)); void main() { gl_Position = mat4(rotation)*VertexPosition; . . . . . }
The uniform variable RadianAngle
defined in the vertex shader is used to apply rotation transformation on the incoming per-vertex attribute VertexPosition
. On the client side, this uniform variable is queried using glGetUniformLocation
. This API returns the index of the uniform variable and stores it in radianAngle
. This index will be used to bind the updated data information that is stored the radian with the glUniform1f
OpenGL ES 3.0 API. Finally, the updated data reaches the vertex shader executable, where the general form of the Euler rotation is calculated:
mat2 rotation = mat2(cos(RadianAngle),sin(RadianAngle), -sin(RadianAngle),cos(RadianAngle));
The rotation transformation is calculated in the form of 2 x 2 matrix rotation, which is later promoted to a 4 x 4 matrix when multiplied by VertexPosition
. The resultant vertices cause to rotate the triangle in a 2D space.
Refer to the Grouping uniforms and creating buffer objects recipe in Chapter 3, New Features of OpenGL ES 3.0