<!DOCTYPE html>
<html>
<head>
<title>orthogonal projection and clip space</title>
</head>
<script id='vshader' type="x-shader/x-vertex">
attribute vec3 a_vertex;
// orthogonal projection matrix
uniform mat4 u_pMatrix;
// model view matrix
uniform mat4 u_mvMatrix;
void main(){
gl_Position = u_pMatrix * u_mvMatrix * vec4(a_vertex, 1);
}
</script>
<script id='fshader' type="x-shader/x-fragement">
void main(){
gl_FragColor = vec4(1, 0, 1, 1);
}
</script>
<body style='margin:0'>
<canvas id='canvas'></canvas>
<script>
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
// init webgl
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// vertices, rectangle, triangle strip
var squareSize = 50;
var vertices = [
squareSize, 0, 0,
0, 0, 0,
squareSize, squareSize, 0,
0, squareSize, 0
];
// the depth will be the canvas width.
var depth = canvas.width;
// transpose of the orthogonal project matrix, y axis flipped to achieve top left as origin
var orthoMatrix = [
2/canvas.width, 0, 0, 0,
0, -2/canvas.height, 0, 0,
0, 0, 2/depth, 0,
-1, 1, -1, 1
];
// setup shader and program
var vshader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vshader, document.getElementById('vshader').textContent);
gl.compileShader(vshader);
var fshader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fshader, document.getElementById('fshader').textContent);
gl.compileShader(fshader);
var program = gl.createProgram();
gl.attachShader(program, vshader);
gl.attachShader(program, fshader);
gl.linkProgram(program);
gl.useProgram(program);
// get shader uniform and attribute location
var vertexLocation = gl.getAttribLocation(program, 'a_vertex');
var projMatrixLocation = gl.getUniformLocation(program, 'u_pMatrix');
var mvMatrixLocation = gl.getUniformLocation(program, 'u_mvMatrix');
// vertex buffer object
var vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// how to draw the vertices, 3 components, float type, not normalized, no interleaved element.
gl.vertexAttribPointer(vertexLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vertexLocation);
// set projection matrix
gl.uniformMatrix4fv(projMatrixLocation, false, orthoMatrix);
// draw the rectangle tween to the target bottom right
var targetX = canvas.width - squareSize;
var targetY = canvas.height - squareSize;
var x = 0;
var y = 0;
function render(){
gl.clear(gl.COLOR_BUFFER_BIT);
x += (targetX - x)/80;
y += (targetY - y)/80;
// model view matrix
var mvMatrix = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, 0, 1
];
// update shader model view matrix
gl.uniformMatrix4fv(mvMatrixLocation, false, mvMatrix);
// draw 4 vertices
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
requestAnimFrame(render);
}
requestAnimFrame(render);
</script>
</body>
</html>