UNPKG

wggl

Version:

A friendly interface to shaders

92 lines (91 loc) 4.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var uniform_1 = require("./uniform"); var primitives_1 = require("./primitives"); // Bakes a vertex and fragment shader into a canvas and returns an object // for operating with the resulting webgl program var WgglProgram = /** @class */ (function () { function WgglProgram(canvas, bindPointers, program) { this.canvas = canvas; this.bindPointers = bindPointers; this.program = program; this.gl = canvas.getContext("webgl"); } WgglProgram.prototype.draw = function (values, drawMode, offset, size, keepCurrentViewport) { var _this = this; if (drawMode === void 0) { drawMode = primitives_1.DrawModes.TRIANGLE_STRIP; } if (offset === void 0) { offset = 0; } if (size === void 0) { size = 4; } if (keepCurrentViewport === void 0) { keepCurrentViewport = false; } var _a = this, canvas = _a.canvas, gl = _a.gl; var textureCounter = 0; if (!keepCurrentViewport) gl.useProgram(this.program); // Pass values to the GPU Object.keys(values).forEach(function (key) { var value = values[key]; var attr = _this.bindPointers[key]; switch (attr.parameters.glType) { case primitives_1.GlType.attribute: gl.enableVertexAttribArray(attr.location); gl.bindBuffer(gl.ARRAY_BUFFER, attr.buffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(value), gl.STATIC_DRAW); var _a = attr.parameters, size_1 = _a.size, normalize = _a.normalize, stride = _a.stride, offset_1 = _a.offset; gl.vertexAttribPointer(attr.location, size_1, gl.FLOAT, normalize, stride, offset_1); break; case primitives_1.GlType.uniform: // TODO: Could be simplified by making the UniformType valies the single characters var typeModifier = attr.parameters.type === uniform_1.UniformType.float ? "f" : "i"; if (isAnyArray(value)) { if (value.length > 4) { throw new Error("Value of uniform type has more than the maximum four dimensions"); } // Dynamic GL method name, (e.g., gl.uniform4fv) gl["uniform" + value.length + typeModifier + "v"](attr.location, value); } else if (value instanceof WebGLTexture && gl.isTexture(value)) { // bind texture gl.activeTexture(gl.TEXTURE0 + textureCounter); gl.bindTexture(gl.TEXTURE_2D, value); gl.uniform1i(attr.location, textureCounter); textureCounter++; } else if (typeof value !== "number" && typeof value !== "boolean") { throw new Error("Value of uniform type must be a number, boolean, or array"); } else { gl["uniform1" + typeModifier](attr.location, value); } break; } }); // Draw if (!keepCurrentViewport) { gl.viewport(0, 0, canvas.width, canvas.height); } gl.drawArrays(gl[drawMode], offset, size); }; WgglProgram.prototype.drawTo = function (buffer, values, drawMode, offset, size) { if (drawMode === void 0) { drawMode = primitives_1.DrawModes.TRIANGLE_STRIP; } if (offset === void 0) { offset = 0; } if (size === void 0) { size = 4; } var gl = this.gl; var texture = buffer.texture; // Use the provided program to draw to the provided buffer gl.useProgram(this.program); gl.bindFramebuffer(gl.FRAMEBUFFER, buffer.buffer); gl.viewport(0, 0, texture.width, texture.height); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[buffer.attachment], gl[buffer.target], texture.texture, gl[buffer.level]); this.draw(values, drawMode, offset, size, true); // Reset the draw buffer to the screen gl.bindFramebuffer(gl.FRAMEBUFFER, null); }; return WgglProgram; }()); exports.WgglProgram = WgglProgram; function isAnyArray(arr) { if (arr == null) return false; // True when arr is any of the typed arrays or the basic array return /^(Float(32|64)|Int(8|16|32)|Uint(8(Clamped)?|16|32|))?Array$/.test(arr.constructor.name); }