Using Web-GL with Typescript
Sample 1 - Base sample code to display a single coloured triangle.
This page demonstrates the basic setup required to display geometry using WebGL, running this
example will display a blue rotating rectangle.
I have used the gl-matrix.js library to handle the matrix manipulations and calculations.
The HTML code below contains the basic shader initialisation code for both the Vertex and Fragment shaders and attaches gl-matrix.js & the transpiled Typescript file: app.js.
The example can be downloaded from Github
I have used the gl-matrix.js library to handle the matrix manipulations and calculations.
The HTML code below contains the basic shader initialisation code for both the Vertex and Fragment shaders and attaches gl-matrix.js & the transpiled Typescript file: app.js.
The example can be downloaded from Github

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>TypeScript HTML App</title>
<link rel="stylesheet" href="app.css" type="text/css" />
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
uniform mat4 mVMatrix;
uniform mat4 pMatrix;
void main(void) {
gl_Position = pMatrix * mVMatrix * vec4(aVertexPosition, 1.0);
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
void main(void) {
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
</script>
<script src="gl-matrix.js"></script>
<script src="app.js"></script>
</head>
<body>
<canvas id="CanvasGL" style="border: none;" width="500" height="500"></canvas>
</body>
</html>
The Typescript code below initialises the canvas, buffers, shaders, camera.
declare var mat4: any;
declare var vec3: any;
class Plane {
private gl: WebGLRenderingContext;
private zNear: number = 0.1;
private zFar: number = 100.0;
private projectionMatrix: any = mat4.create();
private aspect: number = 0;
// In radians
private fieldOfView: number = 45 * Math.PI / 180;
private shaderProgram;
private mvMatrix = mat4.create();
private pMatrix = mat4.create();
private vertexPositionBuffer;
private vertexIndexBuffer;
private vertices;
private indices;
constructor() {
var canvas = document.getElementById("CanvasGL");
this.InitGL(canvas)
this.InitShaders();
this.InitBuffers();
this.SetUpCamera();
this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
this.gl.enable(this.gl.DEPTH_TEST);
mat4.translate(this.mvMatrix, this.mvMatrix, vec3.fromValues(0, 0, -7.0))
setInterval(() => this.DrawScene(), 10);
}
private SetUpCamera(): void {
this.aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight;
mat4.perspective(this.pMatrix,
this.fieldOfView,
this.aspect,
this.zNear,
this.zFar);
}
private InitGL(canvas) {
var names = ["webgl", "experimental-webgl", "webkit-3d", "mozwebgl"];
for (var i = 0; i < names.length; ++i) {
try {
this.gl = canvas.getContext(names[i]);
} catch (e) { }
if (this.gl) {
break;
}
}
if (this.gl == null) {
alert("Could not initialise WebGL");
return null;
}
}
private InitShaders() {
var fragmentShader = this.GetShader(this.gl, "shader-fs");
var vertexShader = this.GetShader(this.gl, "shader-vs");
this.shaderProgram = this.gl.createProgram();
this.gl.attachShader(this.shaderProgram, vertexShader);
this.gl.attachShader(this.shaderProgram, fragmentShader);
this.gl.linkProgram(this.shaderProgram);
if (!this.gl.getProgramParameter(this.shaderProgram, this.gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
this.gl.useProgram(this.shaderProgram);
this.shaderProgram.vertexPositionAttribute = this.gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
this.gl.enableVertexAttribArray(this.shaderProgram.vertexPositionAttribute);
this.shaderProgram.pMatrixUniform = this.gl.getUniformLocation(this.shaderProgram, "pMatrix");
this.shaderProgram.mvMatrixUniform = this.gl.getUniformLocation(this.shaderProgram, "mVMatrix");
}
private GetShader(gl, id) {
var shaderScript = (document.getElementById(id));
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
private InitBuffers() {
this.vertexPositionBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer);
this.vertices = [
-1.0, -1.0, 0.0, //v0
1.0, -1.0, 0.0, //v1
0.0, 1.0, 0.0, //v2
];
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.vertices), this.gl.STATIC_DRAW);
this.vertexPositionBuffer.itemSize = 3;
this.vertexPositionBuffer.numItems = 4;
this.vertexIndexBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
this.indices = [0, 1, 2];
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this.indices), this.gl.STATIC_DRAW);
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null);
}
private DrawScene() {
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer);
this.gl.vertexAttribPointer(this.shaderProgram.vertexPositionAttribute, this.vertexPositionBuffer.itemSize, this.gl.FLOAT,
false, 0, 0);
this.SetMatrixUniforms();
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
this.gl.drawElements(this.gl.TRIANGLES, this.indices.length, this.gl.UNSIGNED_SHORT, 0);
}
private SetMatrixUniforms() {
this.gl.uniformMatrix4fv(this.shaderProgram.pMatrixUniform, false, this.pMatrix);
this.gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.mvMatrix);
}
}
window.onload = () => {
var plane = new Plane();
}