pixelbutler
Version:
Low-res bitmap render engine for big screens
109 lines (108 loc) • 4.45 kB
JavaScript
'use strict';
var vertexShaderSource = [
'attribute vec2 a_position;',
'attribute vec2 a_texCoord;',
'varying vec2 v_texCoord;',
'void main() {',
' gl_Position = vec4(a_position, 0, 1);',
' v_texCoord = a_texCoord;',
'}'
].join('\n');
var fragmentShaderSource = [
'precision mediump float;',
'uniform sampler2D u_image;',
'varying vec2 v_texCoord;',
'void main() {',
' gl_FragColor = texture2D(u_image, v_texCoord);',
'}'
].join('\n');
function loadShader(gl, shaderSource, shaderType) {
var shader = gl.createShader(shaderType);
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
throw new Error('error compiling shader "' + shader + '":' + gl.getShaderInfoLog(shader));
}
return shader;
}
var WebGLRender = (function () {
function WebGLRender(bitmap, canvas) {
this.canvas = canvas;
this.width = bitmap.width;
this.height = bitmap.height;
if (!bitmap.buffer || !Uint8Array) {
throw new Error('bitmap doesn\'t support buffer operations');
}
this.px = new Uint8Array(bitmap.buffer);
if (!window.WebGLRenderingContext) {
throw new Error('browser does not support WegGL');
}
var glOpts = { alpha: false };
var gl = this.gl = this.canvas.getContext('webgl', glOpts) || this.canvas.getContext('experimental-webgl', glOpts);
if (!gl) {
throw new Error('could not create WebGL context');
}
var program = gl.createProgram();
gl.attachShader(program, loadShader(gl, vertexShaderSource, gl.VERTEX_SHADER));
gl.attachShader(program, loadShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER));
gl.linkProgram(program);
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
throw new Error(('error in program linking:' + gl.getProgramInfoLog(program)));
}
gl.useProgram(program);
this.positionLocation = gl.getAttribLocation(program, 'a_position');
this.texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
this.positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
gl.enableVertexAttribArray(this.positionLocation);
gl.vertexAttribPointer(this.positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
-1.0, 1.0,
1.0, -1.0,
1.0, 1.0
]), gl.STATIC_DRAW);
this.texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer);
gl.enableVertexAttribArray(this.texCoordLocation);
gl.vertexAttribPointer(this.texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
0.0, 0.0,
1.0, 1.0,
1.0, 0.0
]), gl.STATIC_DRAW);
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.colorMask(true, true, true, false);
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
}
WebGLRender.prototype.resize = function () {
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
};
WebGLRender.prototype.update = function () {
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGB, this.width, this.height, 0, this.gl.RGB, this.gl.UNSIGNED_BYTE, this.px);
this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
};
WebGLRender.prototype.destruct = function () {
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.gl = null;
this.px = null;
this.canvas = null;
};
return WebGLRender;
})();
module.exports = WebGLRender;