UNPKG

mesh-gradient.js

Version:

A tiny utility to generate mesh gradients in a HTML canvas.

406 lines (405 loc) 23.2 kB
"use strict"; /* * Stripe WebGl Gradient Animation * All Credits to Stripe.com * ScrollObserver functionality to disable animation when not scrolled into view has been disabled and * commented out for now. * https://kevinhufnagl.com */ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MiniGl = exports.normalizeColor = void 0; //Converting colors to proper format function normalizeColor(hexCode) { return [((hexCode >> 16) & 255) / 255, ((hexCode >> 8) & 255) / 255, (255 & hexCode) / 255]; } exports.normalizeColor = normalizeColor; ['SCREEN', 'LINEAR_LIGHT'].reduce(function (hexCode, t, n) { var _a; return Object.assign(hexCode, (_a = {}, _a[t] = n, _a)); }, {}); //Essential functionality of WebGl //t = width //n = height var MiniGl = /** @class */ (function () { function MiniGl(canvas, width, height, debug) { if (debug === void 0) { debug = false; } var _miniGl = this, debug_output = -1 !== document.location.search.toLowerCase().indexOf('debug=webgl'); (_miniGl.canvas = canvas), (_miniGl.gl = _miniGl.canvas.getContext('webgl', { antialias: true, preserveDrawingBuffer: true, })), (_miniGl.meshes = []); var context = _miniGl.gl; width && height && this.setSize(width, height), _miniGl.lastDebugMsg, (_miniGl.debug = debug && debug_output ? function (e) { var t = new Date(); t - _miniGl.lastDebugMsg > 1e3 && console.log('---'), console.log.apply(console, __spreadArray([t.toLocaleTimeString() + Array(Math.max(0, 32 - e.length)).join(' ') + e + ': '], Array.from(arguments).slice(1), false)), (_miniGl.lastDebugMsg = t); } : function () { }), Object.defineProperties(_miniGl, { Material: { enumerable: false, value: /** @class */ (function () { function value(vertexShaders, fragments, uniforms) { if (uniforms === void 0) { uniforms = {}; } var material = this; function getShaderByType(type, source) { var shader = context.createShader(type); return (context.shaderSource(shader, source), context.compileShader(shader), context.getShaderParameter(shader, context.COMPILE_STATUS) || console.error(context.getShaderInfoLog(shader)), _miniGl.debug('Material.compileShaderSource', { source: source, }), shader); } function getUniformVariableDeclarations(uniforms, type) { return Object.entries(uniforms) .map(function (_a) { var uniform = _a[0], value = _a[1]; return value.getDeclaration(uniform, type); }) .join('\n'); } (material.uniforms = uniforms), (material.uniformInstances = []); var prefix = '\n precision highp float;\n '; (material.vertexSource = "\n ".concat(prefix, "\n attribute vec4 position;\n attribute vec2 uv;\n attribute vec2 uvNorm;\n ").concat(getUniformVariableDeclarations(_miniGl.commonUniforms, 'vertex'), "\n ").concat(getUniformVariableDeclarations(uniforms, 'vertex'), "\n ").concat(vertexShaders, "\n ")), (material.Source = "\n ".concat(prefix, "\n ").concat(getUniformVariableDeclarations(_miniGl.commonUniforms, 'fragment'), "\n ").concat(getUniformVariableDeclarations(uniforms, 'fragment'), "\n ").concat(fragments, "\n ")), (material.vertexShader = getShaderByType(context.VERTEX_SHADER, material.vertexSource)), (material.fragmentShader = getShaderByType(context.FRAGMENT_SHADER, material.Source)), (material.program = context.createProgram()), context.attachShader(material.program, material.vertexShader), context.attachShader(material.program, material.fragmentShader), context.linkProgram(material.program), context.getProgramParameter(material.program, context.LINK_STATUS) || console.error(context.getProgramInfoLog(material.program)), context.useProgram(material.program), material.attachUniforms(void 0, _miniGl.commonUniforms), material.attachUniforms(void 0, material.uniforms); } //t = uniform value.prototype.attachUniforms = function (name, uniforms) { //n = material var material = this; void 0 === name ? Object.entries(uniforms).forEach(function (_a) { var name = _a[0], uniform = _a[1]; material.attachUniforms(name, uniform); }) : 'array' == uniforms.type ? uniforms.value.forEach(function (uniform, i) { return material.attachUniforms("".concat(name, "[").concat(i, "]"), uniform); }) : 'struct' == uniforms.type ? Object.entries(uniforms.value).forEach(function (_a) { var uniform = _a[0], i = _a[1]; return material.attachUniforms("".concat(name, ".").concat(uniform), i); }) : (_miniGl.debug('Material.attachUniforms', { name: name, uniform: uniforms, }), material.uniformInstances.push({ uniform: uniforms, location: context.getUniformLocation(material.program, name), })); }; return value; }()), }, Uniform: { enumerable: !1, value: /** @class */ (function () { function value(e) { (this.type = 'float'), Object.assign(this, e); (this.typeFn = { float: '1f', int: '1i', vec2: '2fv', vec3: '3fv', vec4: '4fv', mat4: 'Matrix4fv', }[this.type] || '1f'), this.update(); } value.prototype.update = function (value) { void 0 !== this.value && context["uniform".concat(this.typeFn)](value, 0 === this.typeFn.indexOf('Matrix') ? this.transpose : this.value, 0 === this.typeFn.indexOf('Matrix') ? this.value : null); }; //e - name //t - type //n - length value.prototype.getDeclaration = function (name, type, length) { var uniform = this; if (uniform.excludeFrom !== type) { if ('array' === uniform.type) return (uniform.value[0].getDeclaration(name, type, uniform.value.length) + "\nconst int ".concat(name, "_length = ").concat(uniform.value.length, ";")); if ('struct' === uniform.type) { var name_no_prefix = name.replace('u_', ''); return ((name_no_prefix = name_no_prefix.charAt(0).toUpperCase() + name_no_prefix.slice(1)), "uniform struct ".concat(name_no_prefix, " \n {\n") + Object.entries(uniform.value) .map(function (_a) { var name = _a[0], uniform = _a[1]; return uniform.getDeclaration(name, type).replace(/^uniform/, ''); }) .join('') + "\n} ".concat(name).concat(length > 0 ? "[".concat(length, "]") : '', ";")); } return "uniform ".concat(uniform.type, " ").concat(name).concat(length > 0 ? "[".concat(length, "]") : '', ";"); } }; return value; }()), }, PlaneGeometry: { enumerable: !1, value: /** @class */ (function () { function value(width, height, n, i, orientation) { context.createBuffer(), (this.attributes = { position: new _miniGl.Attribute({ target: context.ARRAY_BUFFER, size: 3, }), uv: new _miniGl.Attribute({ target: context.ARRAY_BUFFER, size: 2, }), uvNorm: new _miniGl.Attribute({ target: context.ARRAY_BUFFER, size: 2, }), index: new _miniGl.Attribute({ target: context.ELEMENT_ARRAY_BUFFER, size: 3, type: context.UNSIGNED_SHORT, }), }), this.setTopology(n, i), this.setSize(width, height, orientation); } value.prototype.setTopology = function (e, t) { if (e === void 0) { e = 1; } if (t === void 0) { t = 1; } var n = this; (n.xSegCount = e), (n.ySegCount = t), (n.vertexCount = (n.xSegCount + 1) * (n.ySegCount + 1)), (n.quadCount = n.xSegCount * n.ySegCount * 2), (n.attributes.uv.values = new Float32Array(2 * n.vertexCount)), (n.attributes.uvNorm.values = new Float32Array(2 * n.vertexCount)), (n.attributes.index.values = new Uint16Array(3 * n.quadCount)); for (var e_1 = 0; e_1 <= n.ySegCount; e_1++) for (var t_1 = 0; t_1 <= n.xSegCount; t_1++) { var i = e_1 * (n.xSegCount + 1) + t_1; if (((n.attributes.uv.values[2 * i] = t_1 / n.xSegCount), (n.attributes.uv.values[2 * i + 1] = 1 - e_1 / n.ySegCount), (n.attributes.uvNorm.values[2 * i] = (t_1 / n.xSegCount) * 2 - 1), (n.attributes.uvNorm.values[2 * i + 1] = 1 - (e_1 / n.ySegCount) * 2), t_1 < n.xSegCount && e_1 < n.ySegCount)) { var s = e_1 * n.xSegCount + t_1; (n.attributes.index.values[6 * s] = i), (n.attributes.index.values[6 * s + 1] = i + 1 + n.xSegCount), (n.attributes.index.values[6 * s + 2] = i + 1), (n.attributes.index.values[6 * s + 3] = i + 1), (n.attributes.index.values[6 * s + 4] = i + 1 + n.xSegCount), (n.attributes.index.values[6 * s + 5] = i + 2 + n.xSegCount); } } n.attributes.uv.update(), n.attributes.uvNorm.update(), n.attributes.index.update(), _miniGl.debug('Geometry.setTopology', { uv: n.attributes.uv, uvNorm: n.attributes.uvNorm, index: n.attributes.index, }); }; value.prototype.setSize = function (width, height, orientation) { if (width === void 0) { width = 1; } if (height === void 0) { height = 1; } if (orientation === void 0) { orientation = 'xz'; } var geometry = this; (geometry.width = width), (geometry.height = height), (geometry.orientation = orientation), (geometry.attributes.position.values && geometry.attributes.position.values.length === 3 * geometry.vertexCount) || (geometry.attributes.position.values = new Float32Array(3 * geometry.vertexCount)); var o = width / -2, r = height / -2, segment_width = width / geometry.xSegCount, segment_height = height / geometry.ySegCount; for (var yIndex = 0; yIndex <= geometry.ySegCount; yIndex++) { var t = r + yIndex * segment_height; for (var xIndex = 0; xIndex <= geometry.xSegCount; xIndex++) { var r_1 = o + xIndex * segment_width, l = yIndex * (geometry.xSegCount + 1) + xIndex; (geometry.attributes.position.values[3 * l + 'xyz'.indexOf(orientation[0])] = r_1), (geometry.attributes.position.values[3 * l + 'xyz'.indexOf(orientation[1])] = -t); } } geometry.attributes.position.update(), _miniGl.debug('Geometry.setSize', { position: geometry.attributes.position, }); }; return value; }()), }, Mesh: { enumerable: !1, value: /** @class */ (function () { function value(geometry, material) { var mesh = this; (mesh.geometry = geometry), (mesh.material = material), (mesh.wireframe = !1), (mesh.attributeInstances = []), Object.entries(mesh.geometry.attributes).forEach(function (_a) { var e = _a[0], attribute = _a[1]; mesh.attributeInstances.push({ attribute: attribute, location: attribute.attach(e, mesh.material.program), }); }), _miniGl.meshes.push(mesh), _miniGl.debug('Mesh.constructor', { mesh: mesh, }); } value.prototype.draw = function () { context.useProgram(this.material.program), this.material.uniformInstances.forEach(function (_a) { var e = _a.uniform, t = _a.location; return e.update(t); }), this.attributeInstances.forEach(function (_a) { var e = _a.attribute, t = _a.location; return e.use(t); }), context.drawElements(this.wireframe ? context.LINES : context.TRIANGLES, this.geometry.attributes.index.values.length, context.UNSIGNED_SHORT, 0); }; value.prototype.remove = function () { var _this = this; _miniGl.meshes = _miniGl.meshes.filter(function (e) { return e != _this; }); }; return value; }()), }, Attribute: { enumerable: !1, value: /** @class */ (function () { function value(e) { (this.type = context.FLOAT), (this.normalized = !1), (this.buffer = context.createBuffer()), Object.assign(this, e), this.update(); } value.prototype.update = function () { void 0 !== this.values && (context.bindBuffer(this.target, this.buffer), context.bufferData(this.target, this.values, context.STATIC_DRAW)); }; value.prototype.attach = function (e, t) { var n = context.getAttribLocation(t, e); return (this.target === context.ARRAY_BUFFER && (context.enableVertexAttribArray(n), context.vertexAttribPointer(n, this.size, this.type, this.normalized, 0, 0)), n); }; value.prototype.use = function (e) { context.bindBuffer(this.target, this.buffer), this.target === context.ARRAY_BUFFER && (context.enableVertexAttribArray(e), context.vertexAttribPointer(e, this.size, this.type, this.normalized, 0, 0)); }; return value; }()), }, }); var a = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; _miniGl.commonUniforms = { projectionMatrix: new _miniGl.Uniform({ type: 'mat4', value: a, }), modelViewMatrix: new _miniGl.Uniform({ type: 'mat4', value: a, }), resolution: new _miniGl.Uniform({ type: 'vec2', value: [1, 1], }), aspectRatio: new _miniGl.Uniform({ type: 'float', value: 1, }), }; } MiniGl.prototype.setSize = function (e, t, e1, t1) { if (e === void 0) { e = 640; } if (t === void 0) { t = 480; } if (e1 === void 0) { e1 = 640; } if (t1 === void 0) { t1 = 480; } (this.width = e), (this.height = t), (this.canvas.width = e1), (this.canvas.height = t1), this.gl.viewport(0, 0, e1, t1), (this.commonUniforms.resolution.value = [e1, t1]), (this.commonUniforms.aspectRatio.value = e1 / t1), this.debug('MiniGL.setSize', { width: e, height: t, }); }; //left, right, top, bottom, near, far MiniGl.prototype.setOrthographicCamera = function (e, t, n, i, s) { if (e === void 0) { e = 0; } if (t === void 0) { t = 0; } if (n === void 0) { n = 0; } if (i === void 0) { i = -2e3; } if (s === void 0) { s = 2e3; } (this.commonUniforms.projectionMatrix.value = [ 2 / this.width, 0, 0, 0, 0, 2 / this.height, 0, 0, 0, 0, 2 / (i - s), 0, e, t, n, 1, ]), this.debug('setOrthographicCamera', this.commonUniforms.projectionMatrix.value); }; MiniGl.prototype.render = function () { this.gl.clearColor(0, 0, 0, 0), this.gl.clearDepth(1), this.meshes.forEach(function (e) { return e.draw(); }); }; return MiniGl; }()); exports.MiniGl = MiniGl;