GLSL varying variables

Above you see a square where each corner has a color and the rest of the square gets its color by interpolating between these corners. The square is drawn using WebGL. There is one draw call, with four vertices: the four corners. Each vertex is assigned a color attribute, and WebGL interpolates between these colors using a varying variable.

// Vertex shader
attribute vec2 a_coord;
attribute vec4 a_color;
varying vec4 v_color;
void main(void) {
  gl_Position = vec4(a_coord, 0.0, 1.0);
  v_color = a_color;
}
// Fragment shader
precision mediump float;
varying vec4 v_color;
void main(void) {
  gl_FragColor = v_color;
}

Notice the declaration of varying vec4 v_color in both shaders. Each call to the vertex shader can assign to v_color. This passes information to the fragment shader. In each call to the fragment shader, the value of v_color comes from prior vertex shader calls. The precise value for a fragment is an interpolation of the value from nearby vertices.

To pass in the initial color, I use another attribute in the vertex shader, a_color. Here’s how we pass in the two attributes, a_coord and a_color:

const coordLoc = gl.getAttribLocation(prog, "a_coord");
const colorLoc = gl.getAttribLocation(prog, "a_color");

const vertexBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  -1,1,  -1,-1,  1,-1,  1, 1,
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(coordLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
gl.vertexAttribPointer(coordLoc, 2, gl.FLOAT, false, 0, 0);

const colorBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  1,0,0,1, 0,1,0,1, 0,0,1,1, 1,1,0,1,
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(colorLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuf);
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);

It’s not clear to me exactly what the interpolation algorithm is. It seems to be linear.

Notice that OpenGL has no hardcoded concepts of “vertex color” or “interpolating colors”. Instead, OpenGL has hardcoded “vertex attributes” and “interpolated attributes” (varyings). We can use varying for more things than color, e.g. normals.

I wrote this because I felt like it. This post is not associated with my employer.