Model Matrix

To perform a translation by (Tx, Ty, Tz), we multiply the modelview matrix by:

To perform a scaling by (Sx, Sy, Sz), we multiply the modelview matrix by:

To perform a rotation by Θ about an axis in the direction of the unit vector (ux, uy, uz), we multiply the modelview matrix by:

This displays a rotating rectangle at the right of the canvas. Note that the transformations are applied in the reversed order, because of the way they are multiplied.
RESETRUNFULL
// /shared/webgl-library.js
Matrix4.prototype.translate = function(x,y,z){
   this.multiply_matrix([1,0,0,0,  0,1,0,0,  0,0,1,0,  x,y,z,1]);
}
Matrix4.prototype.scale = function(x,y,z){
   this.multiply_matrix([x,0,0,0,  0,y,0,0,  0,0,z,0,  0,0,0,1]);
}
Matrix4.prototype.rotate = function(degrees,x,y,z){
   var e = new Array(16);
   var r = Math.PI * degrees / 180;
   var s = Math.sin(r);
   var c = Math.cos(r);
   var nc = 1-c;   // Normalize (x,y,z) to a unit vector
   var l = Math.sqrt(x*x + y*y + z*z);
   x/=l;
   y/=l;
   z/=l;
   e[ 0] = x*x*nc + c;
   e[ 1] = x*y*nc + z*s;
   e[ 2] = z*x*nc - y*s;
   e[ 3] = 0;
   e[ 4] = x*y*nc - z*s;
   e[ 5] = y*y*nc + c;
   e[ 6] = y*z*nc + x*s;
   e[ 7] = 0;
   e[ 8] = z*x*nc + y*s;
   e[ 9] = y*z*nc - x*s;
   e[10] = z*z*nc + c;
   e[11] = 0;
   e[12] = 0;
   e[13] = 0;
   e[14] = 0;
   e[15] = 1;
   this.multiply_matrix(e);
}

<!DOCTYPE html><html>
<head>
<script src="/shared/webgl-library.js"></script>
<script>
var VS_SOURCE=`
   uniform mat4 modelMatrix;
   attribute vec4 p;
   attribute vec4 c;
   varying vec4 c2;
   void main(){
      c2=c;
      gl_Position = modelMatrix * p; 
   }`;
var FS_SOURCE=`
   precision mediump float;
   varying vec4 c2;
   void main(){
      gl_FragColor=c2;
   }`;
var gl, mm, mmL;
function draw_colored_triangle(){
   var points=new Array();
   var vc= new Float32Array([ 0.0,-0.5,  1.0, 0.0, 0.0,
                             -0.5, 0.5,  0.0, 1.0, 0.0,
                              0.5, 0.5,  0.0, 0.0, 1.0]);
   var ESIZE=vc.BYTES_PER_ELEMENT;
   var b=gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER,b);
   gl.bufferData(gl.ARRAY_BUFFER,vc,gl.STATIC_DRAW);
   pL=gl.getAttribLocation(gl.program,'p');
   gl.vertexAttribPointer(pL,2,gl.FLOAT,false,ESIZE*5,0);
   gl.enableVertexAttribArray(pL);
   cL=gl.getAttribLocation(gl.program,'c');
   gl.vertexAttribPointer(cL,3,gl.FLOAT,false,ESIZE*5,ESIZE*2);
   gl.enableVertexAttribArray(cL);
   gl.clearColor(0.0,0.0,0.0,1.0);
   gl.clear(gl.COLOR_BUFFER_BIT);
   gl.drawArrays(gl.TRIANGLES,0,3);
}
function start(){
   var canvas = document.getElementById("myCanvas");
   gl = canvas.getContext("webgl");
   initShaders(gl, VS_SOURCE, FS_SOURCE);
   mm = new Matrix4();
   mmL = gl.getUniformLocation(gl.program,  'modelMatrix');
   mm.translate(0.5, 0, 0);
   mm.scale(0.5, 0.5, 0.5);
   var tick = function(){
      mm.rotate(1, 0, 0, 1);  // rotates one degree every frame
      gl.uniformMatrix4fv(mmL, false, new Float32Array(mm.entries));
      draw_colored_triangle();
      requestAnimationFrame(tick);
   };
   tick();
}
</script>
</head>
<body onload="start()">
   <canvas id="myCanvas" width="500" height="500"></canvas>
</body>
</html>