wggl
Version:
A friendly interface to shaders
107 lines (106 loc) • 4.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var primitives_1 = require("./primitives");
var program_1 = require("./program");
var Wggl = /** @class */ (function () {
function Wggl(canvas, vertShader, fragShader) {
this.canvas = canvas;
this.gl = canvas.getContext("webgl");
var programs;
if (vertShader && fragShader) {
programs = { default: [vertShader, fragShader] };
}
else {
programs = vertShader;
}
// do things with programs
this.setupPrograms(programs);
this.reset();
// If there is a default program, "hoist" its methods to the Wggl instance
// wggl.default.draw() ==> wggl.draw();
// wggl.default.drawTo() ==> wggl.drawTo();
if (this.default) {
var defaultProgram = this.default;
this.draw = defaultProgram.draw.bind(this.default);
this.drawTo = defaultProgram.drawTo.bind(this.default);
}
}
Wggl.prototype.setupPrograms = function (programs) {
var _this = this;
Object.keys(programs).forEach(function (programName) {
var _a = programs[programName], vShader = _a[0], fShader = _a[1];
var gl = _this.gl;
if (_this[programName] != null) {
console.warn("Skipping program " + programName + ". It is either a duplicate program or uses a reserved name");
}
var bindPointers = {};
var vs = createShader(gl, gl.VERTEX_SHADER, vShader.src);
var fs = createShader(gl, gl.FRAGMENT_SHADER, fShader.src);
var program = createProgram(gl, vs, fs);
mergeAttrs(gl, program, bindPointers, vShader.attrs);
mergeAttrs(gl, program, bindPointers, fShader.attrs);
Object.keys(bindPointers).forEach(function (key) {
var value = bindPointers[key];
if (value.parameters.glType === primitives_1.GlType.attribute) {
value.buffer = gl.createBuffer();
}
});
_this[programName] = new program_1.WgglProgram(_this.canvas, bindPointers, program);
});
};
Wggl.prototype.reset = function () {
var _a = this, gl = _a.gl, canvas = _a.canvas;
var scale = Math.min(window.devicePixelRatio, 2);
canvas.width = Math.floor(canvas.clientWidth * scale);
canvas.height = Math.floor(canvas.clientHeight * scale);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
};
return Wggl;
}());
exports.Wggl = Wggl;
function mergeAttrs(gl, program, source, attrs) {
Object.keys(attrs).forEach(function (attr) {
if (source[attr] != null) {
console.warn("Attribute " + attr + " is being bound multiple times. Variable names should be unique across shaders and primitives");
}
source[attr] = {
location: locationForAttr(gl, program, attr, attrs[attr]),
parameters: attrs[attr]
};
});
}
function locationForAttr(gl, program, key, value) {
switch (value.glType) {
case primitives_1.GlType.attribute:
return gl.getAttribLocation(program, key);
case primitives_1.GlType.uniform:
return gl.getUniformLocation(program, key);
}
}
function createShader(gl, type, source) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
var isCompiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!isCompiled) {
var err = gl.getShaderInfoLog(shader);
gl.deleteShader(shader);
throw new Error(err);
}
return shader;
}
function createProgram(gl, vertexShader, fragmentShader) {
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
var isLinked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!isLinked) {
var err = gl.getProgramInfoLog(program);
gl.deleteProgram(program);
throw new Error(err);
}
return program;
}