Uniforms
Vertex attributes are per-vertex data. Which means that every vertex has its own attribute values. However you also need draw call level parameters — values which are shared between all vertices or pixels within a whole GLSL program. For example you could utilize a current time, a scale factor, or some other parameters you want use to configure a rendering of a given geometry. To achieve that you should use GLSL uniforms.
Let's take a vertex shader from the previous lesson and update it in the following way:
#version 300 es
precision highp float;
uniform float time; // Yep, that's draw call level parameter
in vec2 position;
void main(void)
{
// Let's utilize the current time to rotate the current vertex
vec2 rotated = vec2
(
position.x * cos(time) - position.y * sin(time),
position.x * sin(time) + position.y * cos(time)
);
// And let's put the rotated vertex to the output
gl_Position = vec4(rotated, 0.0, 1.0);
}
Now, let's remember our draw
function:
function draw(timestamp)
{
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.drawArrays(gl.TRIANGLES, 0, 3);
window.requestAnimationFrame(draw);
}
To set a uniform value we should find a uniform location in our GLSL program first. That should be done only once. After that we can set a uniform value by its location:
// We found a uniform location here
// "time" is a uniform name in our vertex shader
const time = gl.getUniformLocation(program, "time");
function draw(timestamp)
{
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
// We set a value of the uniform here
gl.uniform1f(time, timestamp / 1000);
gl.drawArrays(gl.TRIANGLES, 0, 3);
window.requestAnimationFrame(draw);
}
Save everything and refresh the page. Now you should see our triangle rotating: