Frontend Development 11 min read

Dynamic Control of WebGL Shaders: Attributes, Uniforms, and Buffer Objects

This tutorial explains how to dynamically control WebGL vertex and fragment shaders by using attribute and uniform variables, assign values from JavaScript, manage buffer objects for large vertex datasets, and render multiple points with proper WebGL API calls.

JD Tech
JD Tech
JD Tech
Dynamic Control of WebGL Shaders: Attributes, Uniforms, and Buffer Objects

After creating a WebGL program, dynamic control of shaders is required to achieve the desired visual effects. This article introduces the two key variable types— attribute for vertex shaders and uniform for both vertex and fragment shaders—that bridge JavaScript and GLSL ES.

Making Vertex Positions Dynamic

Replace fixed vec4 values in the vertex shader with variables and use attribute to pass data from JavaScript.

var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
'  gl_Position = a_Position;\n' +
'  gl_PointSize = 10.0;\n' +
'}\n';

Obtain the attribute location and assign values:

var aPosition = gl.getAttribLocation(gl.program, 'a_Position');
if (aPosition < 0) { console.log('Failed to get the storage location of a_Position'); }
gl.vertexAttrib3f(aPosition, 1.0, 1.0, 0.0);
// Or using a Float32Array
var p = new Float32Array([1.0, 1.0, 1.0]);
gl.vertexAttrib3fv(aPosition, p);

The vertexAttrib family follows the naming convention where the suffix indicates the number of components (1‑4), the data type ( f for float, i for integer, etc.), and whether a vector ( v ) is passed.

Fragment Shader Programming

Fragment shaders use uniform variables to receive data from JavaScript.

var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform vec4 vColor;\n' +
'void main() {\n' +
'  gl_FragColor = vColor; // Set the point color\n' +
'}\n';

Get the uniform location and set its value:

var vColor = gl.getUniformLocation(gl.program, 'vColor');
gl.uniform4f(vColor, 1.0, 0.0, 0.0, 1.0);
// Or using a Float32Array
var color = new Float32Array([1.0, 0.0, 0.0, 1.0]);
gl.uniform4fv(vColor, color);

Buffer Objects

To render many vertices efficiently, WebGL provides buffer objects that store vertex data in GPU memory.

Create a buffer: gl.createBuffer()

Bind it to a target: gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)

Upload data: gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)

Link it to an attribute: gl.vertexAttribPointer(...)

Enable the attribute array: gl.enableVertexAttribArray(...)

Example of creating a buffer and drawing 200 points:

var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) { console.log('Failed to create the buffer object'); return -1; }
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, createPoints(), gl.STATIC_DRAW);
var a_position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_position);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 200);

function createPoints() {
  var arr = [];
  var n = 20, m = 10;
  for (var i = 0; i < n; i++) {
    for (var j = 0; j < m; j++) {
      var x = webglX(-(width/2) + i*20);
      var y = webglY((height/2) - j*20);
      var z = -1;
      arr = arr.concat([x, y, z]);
    }
  }
  return new Float32Array(arr);
}

After executing the above steps, a dense set of points appears on the canvas, confirming that the shader programming and buffer handling are correctly implemented.

Further reading: MDN WebGL Uniform Documentation

graphicsJavaScriptGLSLWebGLBufferShaders
JD Tech
Written by

JD Tech

Official JD technology sharing platform. All the cutting‑edge JD tech, innovative insights, and open‑source solutions you’re looking for, all in one place.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.