(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Hydra = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0) er = args[0]; if (er instanceof Error) { // Note: The comments on the `throw` lines are intentional, they show // up in Node's output if this results in an unhandled exception. throw er; // Unhandled 'error' event } // At least give some kind of context to the user var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); err.context = er; throw err; // Unhandled 'error' event } var handler = events[type]; if (handler === undefined) return false; if (typeof handler === 'function') { ReflectApply(handler, this, args); } else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) ReflectApply(listeners[i], this, args); } return true; }; function _addListener(target, type, listener, prepend) { var m; var events; var existing; checkListener(listener); events = target._events; if (events === undefined) { events = target._events = Object.create(null); target._eventsCount = 0; } else { // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (events.newListener !== undefined) { target.emit('newListener', type, listener.listener ? listener.listener : listener); // Re-assign `events` because a newListener handler could have caused the // this._events to be assigned to a new object events = target._events; } existing = events[type]; } if (existing === undefined) { // Optimize the case of one listener. Don't need the extra array object. existing = events[type] = listener; ++target._eventsCount; } else { if (typeof existing === 'function') { // Adding the second element, need to change to array. existing = events[type] = prepend ? [listener, existing] : [existing, listener]; // If we've already got an array, just append. } else if (prepend) { existing.unshift(listener); } else { existing.push(listener); } // Check for listener leak m = _getMaxListeners(target); if (m > 0 && existing.length > m && !existing.warned) { existing.warned = true; // No error code for this since it is a Warning // eslint-disable-next-line no-restricted-syntax var w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' ' + String(type) + ' listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit'); w.name = 'MaxListenersExceededWarning'; w.emitter = target; w.type = type; w.count = existing.length; ProcessEmitWarning(w); } } return target; } EventEmitter.prototype.addListener = function addListener(type, listener) { return _addListener(this, type, listener, false); }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.prependListener = function prependListener(type, listener) { return _addListener(this, type, listener, true); }; function onceWrapper() { if (!this.fired) { this.target.removeListener(this.type, this.wrapFn); this.fired = true; if (arguments.length === 0) return this.listener.call(this.target); return this.listener.apply(this.target, arguments); } } function _onceWrap(target, type, listener) { var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; var wrapped = onceWrapper.bind(state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; } EventEmitter.prototype.once = function once(type, listener) { checkListener(listener); this.on(type, _onceWrap(this, type, listener)); return this; }; EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { checkListener(listener); this.prependListener(type, _onceWrap(this, type, listener)); return this; }; // Emits a 'removeListener' event if and only if the listener was removed. EventEmitter.prototype.removeListener = function removeListener(type, listener) { var list, events, position, i, originalListener; checkListener(listener); events = this._events; if (events === undefined) return this; list = events[type]; if (list === undefined) return this; if (list === listener || list.listener === listener) { if (--this._eventsCount === 0) this._events = Object.create(null); else { delete events[type]; if (events.removeListener) this.emit('removeListener', type, list.listener || listener); } } else if (typeof list !== 'function') { position = -1; for (i = list.length - 1; i >= 0; i--) { if (list[i] === listener || list[i].listener === listener) { originalListener = list[i].listener; position = i; break; } } if (position < 0) return this; if (position === 0) list.shift(); else { spliceOne(list, position); } if (list.length === 1) events[type] = list[0]; if (events.removeListener !== undefined) this.emit('removeListener', type, originalListener || listener); } return this; }; EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { var listeners, events, i; events = this._events; if (events === undefined) return this; // not listening for removeListener, no need to emit if (events.removeListener === undefined) { if (arguments.length === 0) { this._events = Object.create(null); this._eventsCount = 0; } else if (events[type] !== undefined) { if (--this._eventsCount === 0) this._events = Object.create(null); else delete events[type]; } return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { var keys = Object.keys(events); var key; for (i = 0; i < keys.length; ++i) { key = keys[i]; if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = Object.create(null); this._eventsCount = 0; return this; } listeners = events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else if (listeners !== undefined) { // LIFO order for (i = listeners.length - 1; i >= 0; i--) { this.removeListener(type, listeners[i]); } } return this; }; function _listeners(target, type, unwrap) { var events = target._events; if (events === undefined) return []; var evlistener = events[type]; if (evlistener === undefined) return []; if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener]; return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); } EventEmitter.prototype.listeners = function listeners(type) { return _listeners(this, type, true); }; EventEmitter.prototype.rawListeners = function rawListeners(type) { return _listeners(this, type, false); }; EventEmitter.listenerCount = function(emitter, type) { if (typeof emitter.listenerCount === 'function') { return emitter.listenerCount(type); } else { return listenerCount.call(emitter, type); } }; EventEmitter.prototype.listenerCount = listenerCount; function listenerCount(type) { var events = this._events; if (events !== undefined) { var evlistener = events[type]; if (typeof evlistener === 'function') { return 1; } else if (evlistener !== undefined) { return evlistener.length; } } return 0; } EventEmitter.prototype.eventNames = function eventNames() { return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; }; function arrayClone(arr, n) { var copy = new Array(n); for (var i = 0; i < n; ++i) copy[i] = arr[i]; return copy; } function spliceOne(list, index) { for (; index + 1 < list.length; index++) list[index] = list[index + 1]; list.pop(); } function unwrapListeners(arr) { var ret = new Array(arr.length); for (var i = 0; i < ret.length; ++i) { ret[i] = arr[i].listener || arr[i]; } return ret; } function once(emitter, name) { return new Promise(function (resolve, reject) { function errorListener(err) { emitter.removeListener(name, resolver); reject(err); } function resolver() { if (typeof emitter.removeListener === 'function') { emitter.removeListener('error', errorListener); } resolve([].slice.call(arguments)); }; eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); if (name !== 'error') { addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); } }); } function addErrorHandlerIfEventEmitter(emitter, handler, flags) { if (typeof emitter.on === 'function') { eventTargetAgnosticAddListener(emitter, 'error', handler, flags); } } function eventTargetAgnosticAddListener(emitter, name, listener, flags) { if (typeof emitter.on === 'function') { if (flags.once) { emitter.once(name, listener); } else { emitter.on(name, listener); } } else if (typeof emitter.addEventListener === 'function') { // EventTarget does not have `error` event semantics like Node // EventEmitters, we do not listen for `error` events here. emitter.addEventListener(name, function wrapListener(arg) { // IE does not have builtin `{ once: true }` support so we // have to do it manually. if (flags.once) { emitter.removeEventListener(name, wrapListener); } listener(arg); }); } else { throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); } } },{}],2:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { if (superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }) } }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { if (superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } } },{}],3:[function(require,module,exports){ !function(r,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(r="undefined"!=typeof globalThis?globalThis:r||self).Meyda=t()}(this,(function(){"use strict";function r(r,t,e){if(e||2===arguments.length)for(var a,n=0,o=t.length;n0;n--)t[r-n]=t[n-1];return t},sine:function(r){for(var t=Math.PI/(r-1),e=new Float32Array(r),a=0;a1;)r/=2;return 1===r}function n(r,a){if("rect"!==a){if(""!==a&&a||(a="hanning"),e[a]||(e[a]={}),!e[a][r.length])try{e[a][r.length]=t[a](r.length)}catch(r){throw new Error("Invalid windowing function")}r=function(r,t){for(var e=[],a=0;al;)c[s++]=m,l=s*e[f.length-1]/o;c[o]=f.length-1;for(m=0;mu&&f>=0;)o-=a[f],--f;return(f+1)*n},spectralFlatness:function(r){var t=r.ampSpectrum;if("object"!=typeof t)throw new TypeError;for(var e=0,a=0,n=0;n=0&&t[a]<0||t[a-1]<0&&t[a]>=0)&&e++;return e},loudness:s,perceptualSpread:function(r){for(var t=s({ampSpectrum:r.ampSpectrum,barkScale:r.barkScale}),e=0,a=0;ae&&(e=t.specific[a]);return Math.pow((t.total-e)/t.total,2)},perceptualSharpness:function(r){for(var t=s({ampSpectrum:r.ampSpectrum,barkScale:r.barkScale}),e=t.specific,a=0,n=0;na?r:a})),e/=t.length,e=Math.sqrt(e),a/e},melBands:p});function S(r){if(Array.isArray(r)){for(var t=0,e=Array(r.length);t 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.prependListener = noop; process.prependOnceListener = noop; process.listeners = function (name) { return [] } process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],6:[function(require,module,exports){ var inherits = require('inherits') var EventEmitter = require('events').EventEmitter var now = require('right-now') var raf = require('raf') module.exports = Engine function Engine(fn) { if (!(this instanceof Engine)) return new Engine(fn) this.running = false this.last = now() this._frame = 0 this._tick = this.tick.bind(this) if (fn) this.on('tick', fn) } inherits(Engine, EventEmitter) Engine.prototype.start = function() { if (this.running) return this.running = true this.last = now() this._frame = raf(this._tick) return this } Engine.prototype.stop = function() { this.running = false if (this._frame !== 0) raf.cancel(this._frame) this._frame = 0 return this } Engine.prototype.tick = function() { this._frame = raf(this._tick) var time = now() var dt = time - this.last this.emit('tick', dt) this.last = time } },{"events":1,"inherits":2,"raf":7,"right-now":9}],7:[function(require,module,exports){ (function (global){(function (){ var now = require('performance-now') , root = typeof window === 'undefined' ? global : window , vendors = ['moz', 'webkit'] , suffix = 'AnimationFrame' , raf = root['request' + suffix] , caf = root['cancel' + suffix] || root['cancelRequest' + suffix] for(var i = 0; !raf && i < vendors.length; i++) { raf = root[vendors[i] + 'Request' + suffix] caf = root[vendors[i] + 'Cancel' + suffix] || root[vendors[i] + 'CancelRequest' + suffix] } // Some versions of FF have rAF but not cAF if(!raf || !caf) { var last = 0 , id = 0 , queue = [] , frameDuration = 1000 / 60 raf = function(callback) { if(queue.length === 0) { var _now = now() , next = Math.max(0, frameDuration - (_now - last)) last = next + _now setTimeout(function() { var cp = queue.slice(0) // Clear queue here to prevent // callbacks from appending listeners // to the current frame's queue queue.length = 0 for(var i = 0; i < cp.length; i++) { if(!cp[i].cancelled) { try{ cp[i].callback(last) } catch(e) { setTimeout(function() { throw e }, 0) } } } }, Math.round(next)) } queue.push({ handle: ++id, callback: callback, cancelled: false }) return id } caf = function(handle) { for(var i = 0; i < queue.length; i++) { if(queue[i].handle === handle) { queue[i].cancelled = true } } } } module.exports = function(fn) { // Wrap in a new function to prevent // `cancel` potentially being assigned // to the native rAF function return raf.call(root, fn) } module.exports.cancel = function() { caf.apply(root, arguments) } module.exports.polyfill = function(object) { if (!object) { object = root; } object.requestAnimationFrame = raf object.cancelAnimationFrame = caf } }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"performance-now":4}],8:[function(require,module,exports){ (function(aa,ia){"object"===typeof exports&&"undefined"!==typeof module?module.exports=ia():"function"===typeof define&&define.amd?define(ia):aa.createREGL=ia()})(this,function(){function aa(a,b){this.id=Ab++;this.type=a;this.data=b}function ia(a){if(0===a.length)return[];var b=a.charAt(0),c=a.charAt(a.length-1);if(1>>=b;c=(255>>=c;b|=c;c=(15>>=c;b|=c;c=(3>>c>>1}function cb(){function a(a){a:{for(var b=16;268435456>=b;b*=16)if(a<=b){a=b;break a}a=0}b=c[bb(a)>>2];return 0>2].push(a)}var c=J(8,function(){return[]});return{alloc:a,free:b,allocType:function(b,c){var d=null;switch(b){case 5120:d=new Int8Array(a(c),0,c);break;case 5121:d=new Uint8Array(a(c),0,c);break;case 5122:d=new Int16Array(a(2*c),0,c);break;case 5123:d=new Uint16Array(a(2*c),0,c);break;case 5124:d=new Int32Array(a(4*c),0,c);break;case 5125:d=new Uint32Array(a(4*c),0,c);break;case 5126:d=new Float32Array(a(4*c),0,c);break;default:return null}return d.length!== c?d.subarray(0,c):d},freeType:function(a){b(a.buffer)}}}function ma(a){return!!a&&"object"===typeof a&&Array.isArray(a.shape)&&Array.isArray(a.stride)&&"number"===typeof a.offset&&a.shape.length===a.stride.length&&(Array.isArray(a.data)||M(a.data))}function db(a,b,c,e,g,d){for(var n=0;nd&&(d=e.buffer.byteLength,5123===f?d>>=1:5125===f&&(d>>=2));e.vertCount=d;d=h;0>h&&(d=4,h=e.buffer.dimension,1===h&&(d=0),2===h&&(d=1),3===h&&(d=4));e.primType=d}function n(a){e.elementsCount--;delete f[a.id];a.buffer.destroy();a.buffer=null}var f={},r=0,q={uint8:5121,uint16:5123};b.oes_element_index_uint&&(q.uint32=5125);g.prototype.bind=function(){this.buffer.bind()};var t=[];return{create:function(a,b){function k(a){if(a)if("number"===typeof a)h(a),l.primType=4,l.vertCount=a|0, l.type=5121;else{var b=null,c=35044,e=-1,g=-1,f=0,m=0;if(Array.isArray(a)||M(a)||ma(a))b=a;else if("data"in a&&(b=a.data),"usage"in a&&(c=jb[a.usage]),"primitive"in a&&(e=Sa[a.primitive]),"count"in a&&(g=a.count|0),"type"in a&&(m=q[a.type]),"length"in a)f=a.length|0;else if(f=g,5123===m||5122===m)f*=2;else if(5125===m||5124===m)f*=4;d(l,b,c,e,g,f,m)}else h(),l.primType=4,l.vertCount=0,l.type=5121;return k}var h=c.create(null,34963,!0),l=new g(h._buffer);e.elementsCount++;k(a);k._reglType="elements"; k._elements=l;k.subdata=function(a,b){h.subdata(a,b);return k};k.destroy=function(){n(l)};return k},createStream:function(a){var b=t.pop();b||(b=new g(c.create(null,34963,!0,!1)._buffer));d(b,a,35040,-1,-1,0,0);return b},destroyStream:function(a){t.push(a)},getElements:function(a){return"function"===typeof a&&a._elements instanceof g?a._elements:null},clear:function(){S(f).forEach(n)}}}function kb(a){for(var b=x.allocType(5123,a.length),c=0;c>>31<<15,d=(e<<1>>>24)-127,e=e>>13&1023;b[c]=-24>d?g:-14>d?g+(e+1024>>-14-d):15>=e,c.height>>=e,C(c,d[e]),a.mipmask|=1<b;++b)a.images[b]=null;return a}function ib(a){for(var b=a.images,c=0;cb){for(var c=0;c=--this.refCount&&A(this)}});n.profile&&(d.getTotalTextureSize=function(){var a=0;Object.keys(X).forEach(function(b){a+=X[b].stats.size});return a});return{create2D:function(b,c){function e(a,b){var c=f.texInfo;y.call(c);var d=D();"number"===typeof a?"number"===typeof b?v(d,a|0,b|0):v(d,a|0,a|0):a?(O(c,a),N(d,a)):v(d,1,1);c.genMipmaps&&(d.mipmask=(d.width<<1)-1);f.mipmask=d.mipmask;r(f,d);f.internalformat=d.internalformat; e.width=d.width;e.height=d.height;T(f);B(d,3553);R(c,3553);Aa();ib(d);n.profile&&(f.stats.size=Ja(f.internalformat,f.type,d.width,d.height,c.genMipmaps,!1));e.format=J[f.internalformat];e.type=da[f.type];e.mag=oa[c.magFilter];e.min=za[c.minFilter];e.wrapS=ka[c.wrapS];e.wrapT=ka[c.wrapT];return e}var f=new F(3553);X[f.id]=f;d.textureCount++;e(b,c);e.subimage=function(a,b,c,d){b|=0;c|=0;d|=0;var p=h();r(p,f);p.width=0;p.height=0;C(p,a);p.width=p.width||(f.width>>d)-b;p.height=p.height||(f.height>>d)- c;T(f);k(p,3553,b,c,d);Aa();l(p);return e};e.resize=function(b,c){var d=b|0,h=c|0||d;if(d===f.width&&h===f.height)return e;e.width=f.width=d;e.height=f.height=h;T(f);for(var p,w=f.channels,z=f.type,I=0;f.mipmask>>I;++I){var fa=d>>I,ga=h>>I;if(!fa||!ga)break;p=x.zero.allocType(z,fa*ga*w);a.texImage2D(3553,I,f.format,fa,ga,0,f.format,f.type,p);p&&x.zero.freeType(p)}Aa();n.profile&&(f.stats.size=Ja(f.internalformat,f.type,d,h,!1,!1));return e};e._reglType="texture2d";e._texture=f;n.profile&&(e.stats= f.stats);e.destroy=function(){f.decRef()};return e},createCube:function(b,c,e,f,g,ua){function A(a,b,c,d,e,f){var H,Y=m.texInfo;y.call(Y);for(H=0;6>H;++H)p[H]=D();if("number"===typeof a||!a)for(a=a|0||1,H=0;6>H;++H)v(p[H],a,a);else if("object"===typeof a)if(b)N(p[0],a),N(p[1],b),N(p[2],c),N(p[3],d),N(p[4],e),N(p[5],f);else if(O(Y,a),q(m,a),"faces"in a)for(a=a.faces,H=0;6>H;++H)r(p[H],m),N(p[H],a[H]);else for(H=0;6>H;++H)N(p[H],a);r(m,p[0]);m.mipmask=Y.genMipmaps?(p[0].width<<1)-1:p[0].mipmask;m.internalformat= p[0].internalformat;A.width=p[0].width;A.height=p[0].height;T(m);for(H=0;6>H;++H)B(p[H],34069+H);R(Y,34067);Aa();n.profile&&(m.stats.size=Ja(m.internalformat,m.type,A.width,A.height,Y.genMipmaps,!0));A.format=J[m.internalformat];A.type=da[m.type];A.mag=oa[Y.magFilter];A.min=za[Y.minFilter];A.wrapS=ka[Y.wrapS];A.wrapT=ka[Y.wrapT];for(H=0;6>H;++H)ib(p[H]);return A}var m=new F(34067);X[m.id]=m;d.cubeCount++;var p=Array(6);A(b,c,e,f,g,ua);A.subimage=function(a,b,c,p,d){c|=0;p|=0;d|=0;var e=h();r(e,m); e.width=0;e.height=0;C(e,b);e.width=e.width||(m.width>>d)-c;e.height=e.height||(m.height>>d)-p;T(m);k(e,34069+a,c,p,d);Aa();l(e);return A};A.resize=function(b){b|=0;if(b!==m.width){A.width=m.width=b;A.height=m.height=b;T(m);for(var c=0;6>c;++c)for(var p=0;m.mipmask>>p;++p)a.texImage2D(34069+c,p,m.format,b>>p,b>>p,0,m.format,m.type,null);Aa();n.profile&&(m.stats.size=Ja(m.internalformat,m.type,A.width,A.height,!1,!0));return A}};A._reglType="textureCube";A._texture=m;n.profile&&(A.stats=m.stats);A.destroy= function(){m.decRef()};return A},clear:function(){for(var b=0;bc;++c)if(0!==(b.mipmask&1<> c,b.height>>c,0,b.internalformat,b.type,null);else for(var d=0;6>d;++d)a.texImage2D(34069+d,c,b.internalformat,b.width>>c,b.height>>c,0,b.internalformat,b.type,null);R(b.texInfo,b.target)})}}}function Ob(a,b,c,e,g,d){function n(a,b,c){this.target=a;this.texture=b;this.renderbuffer=c;var d=a=0;b?(a=b.width,d=b.height):c&&(a=c.width,d=c.height);this.width=a;this.height=d}function f(a){a&&(a.texture&&a.texture._texture.decRef(),a.renderbuffer&&a.renderbuffer._renderbuffer.decRef())}function r(a,b,c){a&& (a.texture?a.texture._texture.refCount+=1:a.renderbuffer._renderbuffer.refCount+=1)}function q(b,c){c&&(c.texture?a.framebufferTexture2D(36160,b,c.target,c.texture._texture.texture,0):a.framebufferRenderbuffer(36160,b,36161,c.renderbuffer._renderbuffer.renderbuffer))}function t(a){var b=3553,c=null,d=null,e=a;"object"===typeof a&&(e=a.data,"target"in a&&(b=a.target|0));a=e._reglType;"texture2d"===a?c=e:"textureCube"===a?c=e:"renderbuffer"===a&&(d=e,b=36161);return new n(b,c,d)}function m(a,b,c,d, f){if(c)return a=e.create2D({width:a,height:b,format:d,type:f}),a._texture.refCount=0,new n(3553,a,null);a=g.create({width:a,height:b,format:d});a._renderbuffer.refCount=0;return new n(36161,null,a)}function C(a){return a&&(a.texture||a.renderbuffer)}function k(a,b,c){a&&(a.texture?a.texture.resize(b,c):a.renderbuffer&&a.renderbuffer.resize(b,c),a.width=b,a.height=c)}function h(){this.id=O++;R[this.id]=this;this.framebuffer=a.createFramebuffer();this.height=this.width=0;this.colorAttachments=[];this.depthStencilAttachment= this.stencilAttachment=this.depthAttachment=null}function l(a){a.colorAttachments.forEach(f);f(a.depthAttachment);f(a.stencilAttachment);f(a.depthStencilAttachment)}function u(b){a.deleteFramebuffer(b.framebuffer);b.framebuffer=null;d.framebufferCount--;delete R[b.id]}function v(b){var d;a.bindFramebuffer(36160,b.framebuffer);var e=b.colorAttachments;for(d=0;dd;++d){for(m=0;ma;++a)c[a].resize(d);b.width=b.height=d;return b},_reglType:"framebufferCube",destroy:function(){c.forEach(function(a){a.destroy()})}})},clear:function(){S(R).forEach(u)},restore:function(){B.cur=null;B.next=null;B.dirty=!0;S(R).forEach(function(b){b.framebuffer=a.createFramebuffer();v(b)})}})}function ub(){this.w=this.z=this.y= this.x=this.state=0;this.buffer=null;this.size=0;this.normalized=!1;this.type=5126;this.divisor=this.stride=this.offset=0}function Pb(a,b,c,e){a=c.maxAttributes;b=Array(a);for(c=0;c a&&(a=b.stats.uniformsCount)});return a},c.getMaxAttributesCount=function(){var a=0;C.forEach(function(b){b.stats.attributesCount>a&&(a=b.stats.attributesCount)});return a});return{clear:function(){var b=a.deleteShader.bind(a);S(q).forEach(b);q={};S(t).forEach(b);t={};C.forEach(function(b){a.deleteProgram(b.program)});C.length=0;m={};c.shaderCount=0},program:function(a,b,d){var e=m[b];e||(e=m[b]={});var g=e[a];g||(g=new f(b,a),c.shaderCount++,r(g,d),e[a]=g,C.push(g));return g},restore:function(){q= {};t={};for(var a=0;a"+b+"?"+e+".constant["+b+"]:0;"}).join(""),"}}else{", "if(",f,"(",e,".buffer)){",z,"=",g,".createStream(",34962,",",e,".buffer);","}else{",z,"=",g,".getBuffer(",e,".buffer);","}",k,'="type" in ',e,"?",p.glTypes,"[",e,".type]:",z,".dtype;",w.normalized,"=!!",e,".normalized;");d("size");d("offset");d("stride");d("divisor");c("}}");c.exit("if(",w.isStream,"){",g,".destroyStream(",z,");","}");return w})});return f}function M(a){var b=a["static"],c=a.dynamic,d={};Object.keys(b).forEach(function(a){var c=b[a];d[a]=D(function(a,b){return"number"===typeof c|| "boolean"===typeof c?""+c:a.link(c)})});Object.keys(c).forEach(function(a){var b=c[a];d[a]=P(b,function(a,c){return a.invoke(c,b)})});return d}function A(a,b,c,d,e){var f=y(a,e),g=x(a,f,e),h=O(a,e),k=R(a,e),m=E(a,e),ba=g.viewport;ba&&(k.viewport=ba);ba=l("scissor.box");(g=g[ba])&&(k[ba]=g);g=0>1)",v],");")}function b(){c(u,".drawArraysInstancedANGLE(",[q,r,t,v],");")}n?da?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")):b()}function g(){function a(){c(k+".drawElements("+[q,t,C,r+"<<(("+C+"-5121)>>1)"]+");")}function b(){c(k+".drawArrays("+[q,r,t]+");")}n?da?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")): b()}var h=a.shared,k=h.gl,m=h.draw,l=d.draw,n=function(){var e=l.elements,f=b;if(e){if(e.contextDep&&d.contextDynamic||e.propDep)f=c;e=e.append(a,f)}else e=f.def(m,".","elements");e&&f("if("+e+")"+k+".bindBuffer(34963,"+e+".buffer.buffer);");return e}(),q=e("primitive"),r=e("offset"),t=function(){var e=l.count,f=b;if(e){if(e.contextDep&&d.contextDynamic||e.propDep)f=c;e=e.append(a,f)}else e=f.def(m,".","count");return e}();if("number"===typeof t){if(0===t)return}else c("if(",t,"){"),c.exit("}");var v, u;ea&&(v=e("instances"),u=a.instancing);var C=n+".type",da=l.elements&&va(l.elements);ea&&("number"!==typeof v||0<=v)?"string"===typeof v?(c("if(",v,">0){"),f(),c("}else if(",v,"<0){"),g(),c("}")):f():g()}function ca(a,b,c,d,e){b=N();e=b.proc("body",e);ea&&(b.instancing=e.def(b.shared.extensions,".angle_instanced_arrays"));a(b,e,c,d);return b.compile().body}function L(a,b,c,d){wa(a,b);U(a,b,c,d.attributes,function(){return!0});W(a,b,c,d.uniforms,function(){return!0});S(a,b,b,c)}function da(a,b){var c= a.proc("draw",1);wa(a,c);ua(a,c,b.context);K(a,c,b.framebuffer);V(a,c,b);Q(a,c,b.state);G(a,c,b,!1,!0);var d=b.shader.progVar.append(a,c);c(a.shared.gl,".useProgram(",d,".program);");if(b.shader.program)L(a,c,b,b.shader.program);else{var e=a.global.def("{}"),f=c.def(d,".id"),g=c.def(e,"[",f,"]");c(a.cond(g).then(g,".call(this,a0);")["else"](g,"=",e,"[",f,"]=",a.link(function(c){return ca(L,a,b,c,1)}),"(",d,");",g,".call(this,a0);"))}0=--this.refCount&&n(this)};g.profile&&(e.getTotalRenderbufferSize=function(){var a=0;Object.keys(t).forEach(function(b){a+=t[b].stats.size});return a});return{create:function(b,c){function k(b,c){var d=0,e=0,m=32854;"object"===typeof b&&b?("shape"in b?(e=b.shape,d=e[0]|0,e=e[1]|0):("radius"in b&&(d=e=b.radius|0),"width"in b&&(d=b.width|0),"height"in b&&(e=b.height|0)),"format"in b&&(m=f[b.format])): "number"===typeof b?(d=b|0,e="number"===typeof c?c|0:d):b||(d=e=1);if(d!==h.width||e!==h.height||m!==h.format)return k.width=h.width=d,k.height=h.height=e,h.format=m,a.bindRenderbuffer(36161,h.renderbuffer),a.renderbufferStorage(36161,m,d,e),g.profile&&(h.stats.size=Q[h.format]*h.width*h.height),k.format=r[h.format],k}var h=new d(a.createRenderbuffer());t[h.id]=h;e.renderbufferCount++;k(b,c);k.resize=function(b,c){var d=b|0,e=c|0||d;if(d===h.width&&e===h.height)return k;k.width=h.width=d;k.height= h.height=e;a.bindRenderbuffer(36161,h.renderbuffer);a.renderbufferStorage(36161,h.format,d,e);g.profile&&(h.stats.size=Q[h.format]*h.width*h.height);return k};k._reglType="renderbuffer";k._renderbuffer=h;g.profile&&(k.stats=h.stats);k.destroy=function(){h.decRef()};return k},clear:function(){S(t).forEach(n)},restore:function(){S(t).forEach(function(b){b.renderbuffer=a.createRenderbuffer();a.bindRenderbuffer(36161,b.renderbuffer);a.renderbufferStorage(36161,b.format,b.width,b.height)});a.bindRenderbuffer(36161, null)}}},Wa=[];Wa[6408]=4;Wa[6407]=3;var Na=[];Na[5121]=1;Na[5126]=4;Na[36193]=2;var Da=["x","y","z","w"],Ub="blend.func blend.equation stencil.func stencil.opFront stencil.opBack sample.coverage viewport scissor.box polygonOffset.offset".split(" "),Ga={0:0,1:1,zero:0,one:1,"src color":768,"one minus src color":769,"src alpha":770,"one minus src alpha":771,"dst color":774,"one minus dst color":775,"dst alpha":772,"one minus dst alpha":773,"constant color":32769,"one minus constant color":32770,"constant alpha":32771, "one minus constant alpha":32772,"src alpha saturate":776},Xa={never:512,less:513,"<":513,equal:514,"=":514,"==":514,"===":514,lequal:515,"<=":515,greater:516,">":516,notequal:517,"!=":517,"!==":517,gequal:518,">=":518,always:519},Pa={0:0,zero:0,keep:7680,replace:7681,increment:7682,decrement:7683,"increment wrap":34055,"decrement wrap":34056,invert:5386},wb={cw:2304,ccw:2305},xb=new Z(!1,!1,!1,function(){}),Xb=function(a,b){function c(){this.endQueryIndex=this.startQueryIndex=-1;this.sum=0;this.stats= null}function e(a,b,d){var e=n.pop()||new c;e.startQueryIndex=a;e.endQueryIndex=b;e.sum=0;e.stats=d;f.push(e)}if(!b.ext_disjoint_timer_query)return null;var g=[],d=[],n=[],f=[],r=[],q=[];return{beginQuery:function(a){var c=g.pop()||b.ext_disjoint_timer_query.createQueryEXT();b.ext_disjoint_timer_query.beginQueryEXT(35007,c);d.push(c);e(d.length-1,d.length,a)},endQuery:function(){b.ext_disjoint_timer_query.endQueryEXT(35007)},pushScopeStats:e,update:function(){var a,c;a=d.length;if(0!==a){q.length= Math.max(q.length,a+1);r.length=Math.max(r.length,a+1);r[0]=0;var e=q[0]=0;for(c=a=0;c=G.length&&e()}var c=yb(G,a);G[c]=b}}}function q(){var a=S.viewport,b=S.scissor_box;a[0]=a[1]=b[0]=b[1]=0;O.viewportWidth=O.framebufferWidth=O.drawingBufferWidth=a[2]=b[2]=k.drawingBufferWidth;O.viewportHeight=O.framebufferHeight=O.drawingBufferHeight=a[3]=b[3]=k.drawingBufferHeight}function t(){O.tick+=1;O.time=y(); q();V.procs.poll()}function m(){q();V.procs.refresh();B&&B.update()}function y(){return(zb()-D)/1E3}a=Eb(a);if(!a)return null;var k=a.gl,h=k.getContextAttributes();k.isContextLost();var l=Fb(k,a);if(!l)return null;var u=Bb(),v={bufferCount:0,elementsCount:0,framebufferCount:0,shaderCount:0,textureCount:0,cubeCount:0,renderbufferCount:0,maxTextureUnits:0},x=l.extensions,B=Xb(k,x),D=zb(),J=k.drawingBufferWidth,P=k.drawingBufferHeight,O={tick:0,time:0,viewportWidth:J,viewportHeight:P,framebufferWidth:J, framebufferHeight:P,drawingBufferWidth:J,drawingBufferHeight:P,pixelRatio:a.pixelRatio},R=Vb(k,x),J=Pb(k,x,R,u),F=Gb(k,v,a,J),T=Hb(k,x,F,v),Q=Qb(k,u,v,a),A=Kb(k,x,R,function(){V.procs.poll()},O,v,a),M=Wb(k,x,R,v,a),K=Ob(k,x,R,A,M,v),V=Tb(k,u,x,R,F,T,A,K,{},J,Q,{elements:null,primitive:4,count:-1,offset:0,instances:-1},O,B,a),u=Rb(k,K,V.procs.poll,O,h,x,R),S=V.next,L=k.canvas,G=[],U=[],W=[],Z=[a.onDestroy],ca=null;L&&(L.addEventListener("webglcontextlost",g,!1),L.addEventListener("webglcontextrestored", d,!1));var aa=K.setFBO=n({framebuffer:la.define.call(null,1,"framebuffer")});m();h=E(n,{clear:function(a){if("framebuffer"in a)if(a.framebuffer&&"framebufferCube"===a.framebuffer_reglType)for(var b=0;6>b;++b)aa(E({framebuffer:a.framebuffer.faces[b]},a),f);else aa(a,f);else f(null,a)},prop:la.define.bind(null,1),context:la.define.bind(null,2),"this":la.define.bind(null,3),draw:n({}),buffer:function(a){return F.create(a,34962,!1,!1)},elements:function(a){return T.create(a,!1)},texture:A.create2D,cube:A.createCube, renderbuffer:M.create,framebuffer:K.create,framebufferCube:K.createCube,attributes:h,frame:r,on:function(a,b){var c;switch(a){case "frame":return r(b);case "lost":c=U;break;case "restore":c=W;break;case "destroy":c=Z}c.push(b);return{cancel:function(){for(var a=0;a this.add(property)); this.userProps = userProps; } add(name) { if (this.makeGlobal) window[name] = this.parent[name]; // this.sandbox.addToContext(name, `parent.${name}`) } // sets on window as well as synth object if global (not needed for objects, which can be set directly) set(property, value) { if (this.makeGlobal) { window[property] = value; } this.parent[property] = value; } tick() { if (this.makeGlobal) { this.userProps.forEach(property => { this.parent[property] = window[property]; }); // this.parent.speed = window.speed } else {} } eval(code) { this.sandbox.eval(code); } } var _default = EvalSandbox; exports.default = _default; },{"./lib/array-utils.js":20,"./lib/sandbox.js":25}],11:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = formatArguments; var _arrayUtils = _interopRequireDefault(require("./lib/array-utils.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // [WIP] how to treat different dimensions (?) const DEFAULT_CONVERSIONS = { float: { 'vec4': { name: 'sum', args: [[1, 1, 1, 1]] }, 'vec2': { name: 'sum', args: [[1, 1]] } } }; function fillArrayWithDefaults(arr, len) { // fill the array with default values if it's too short while (arr.length < len) { if (arr.length === 3) { // push a 1 as the default for .a in vec4 arr.push(1.0); } else { arr.push(0.0); } } return arr.slice(0, len); } const ensure_decimal_dot = val => { val = val.toString(); if (val.indexOf('.') < 0) { val += '.'; } return val; }; function formatArguments(transform, startIndex, synthContext) { const defaultArgs = transform.transform.inputs; const userArgs = transform.userArgs; const { generators } = transform.synth; const { src } = generators; // depends on synth having src() function return defaultArgs.map((input, index) => { const typedArg = { value: input.default, type: input.type, // isUniform: false, name: input.name, vecLen: 0 // generateGlsl: null // function for creating glsl }; if (typedArg.type === 'float') typedArg.value = ensure_decimal_dot(input.default); if (input.type.startsWith('vec')) { try { typedArg.vecLen = Number.parseInt(input.type.substr(3)); } catch (e) { console.log(`Error determining length of vector input type ${input.type} (${input.name})`); } } // if user has input something for this argument if (userArgs.length > index) { typedArg.value = userArgs[index]; if (typedArg.type === 'vec4') { if (!(typedArg.value.type === "GlslSource" || typedArg.value.getTexture)) { throw new Error("Arguments must be a texture or GlslSource"); } } // do something if a composite or transform if (typeof userArgs[index] === 'function') { // if (typedArg.vecLen > 0) { // expected input is a vector, not a scalar // typedArg.value = (context, props, batchId) => (fillArrayWithDefaults(userArgs[index](props), typedArg.vecLen)) // } else { typedArg.value = (context, props, batchId) => { try { const val = userArgs[index](props); if (typeof val === 'number') { return val; } else { console.warn('function does not return a number', userArgs[index]); } return input.default; } catch (e) { console.warn('ERROR', e); return input.default; } }; // } typedArg.isUniform = true; } else if (userArgs[index].constructor === Array) { // if (typedArg.vecLen > 0) { // expected input is a vector, not a scalar // typedArg.isUniform = true // typedArg.value = fillArrayWithDefaults(typedArg.value, typedArg.vecLen) // } else { // console.log("is Array") // filter out values that are not a number // const filteredArray = userArgs[index].filter((val) => typeof val === 'number') // typedArg.value = (context, props, batchId) => arrayUtils.getValue(filteredArray)(props) typedArg.value = (context, props, batchId) => _arrayUtils.default.getValue(userArgs[index])(props); typedArg.isUniform = true; // } } } if (startIndex < 0) {} else { if (typedArg.value && typedArg.value.transforms) { const final_transform = typedArg.value.transforms[typedArg.value.transforms.length - 1]; if (final_transform.transform.glsl_return_type !== input.type) { const defaults = DEFAULT_CONVERSIONS[input.type]; if (typeof defaults !== 'undefined') { const default_def = defaults[final_transform.transform.glsl_return_type]; if (typeof default_def !== 'undefined') { const { name, args } = default_def; typedArg.value = typedArg.value[name](...args); } } } typedArg.isUniform = false; } else if (typedArg.type === 'float' && typeof typedArg.value === 'number') { typedArg.value = ensure_decimal_dot(typedArg.value); } else if (typedArg.type.startsWith('vec') && typeof typedArg.value === 'object' && Array.isArray(typedArg.value)) { typedArg.isUniform = false; typedArg.value = `${typedArg.type}(${typedArg.value.map(ensure_decimal_dot).join(', ')})`; } else if (input.type === 'sampler2D') { // typedArg.tex = typedArg.value var x = typedArg.value; typedArg.value = () => x.getTexture(); typedArg.isUniform = true; } else { // if passing in a texture reference, when function asks for vec4, convert to vec4 if (typedArg.value.getTexture && input.type === 'vec4') { var x1 = typedArg.value; typedArg.value = src(x1); typedArg.isUniform = false; } } // add tp uniform array if is a function that will pass in a different value on each render frame, // or a texture/ external source if (typedArg.isUniform) { typedArg.name += startIndex; // shaderParams.uniforms.push(typedArg) } } return typedArg; }); } },{"./lib/array-utils.js":20}],12:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _default; var _formatArguments = _interopRequireDefault(require("./format-arguments.js")); var _arrayUtils = _interopRequireDefault(require("./lib/array-utils.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // Add extra functionality to Array.prototype for generating sequences in time // converts a tree of javascript functions to a shader function _default(transforms) { var shaderParams = { uniforms: [], // list of uniforms used in shader glslFunctions: [], // list of functions used in shader fragColor: '' }; var gen = generateGlsl(transforms, shaderParams)('c', 'st'); // console.log(gen) shaderParams.fragColor = gen; // remove uniforms with duplicate names let uniforms = {}; shaderParams.uniforms.forEach(uniform => uniforms[uniform.name] = uniform); shaderParams.uniforms = Object.values(uniforms); return shaderParams; } function generateInputName(v, index) { return `${v}_i${index}`; } function generateGlsl(transforms, shaderParams) { var generator = (c, uv) => ''; transforms.forEach((transform, i) => { // Accumulate uniforms to lazily add them to the output shader let inputs = (0, _formatArguments.default)(transform, shaderParams.uniforms.length); inputs.forEach(input => { if (input.isUniform) shaderParams.uniforms.push(input); }); // Lazily generate glsl function definition if (!contains(transform, shaderParams.glslFunctions)) shaderParams.glslFunctions.push(transform); var prev = generator; if (transform.transform.type === 'src') { generator = (c, uv) => `${generateInputs(inputs, shaderParams)(`${c}${i}`, uv)} vec4 ${c} = ${shaderString(`${c}${i}`, uv, transform.name, inputs)};`; } else if (transform.transform.type === 'color') { generator = (c, uv) => `${generateInputs(inputs, shaderParams)(`${c}${i}`, uv)} ${prev(c, uv)} ${c} = ${shaderString(`${c}${i}`, `${c}`, transform.name, inputs)};`; } else if (transform.transform.type === 'coord') { generator = (c, uv) => `${generateInputs(inputs, shaderParams)(`${c}${i}`, uv)} ${uv} = ${shaderString(`${c}${i}`, `${uv}`, transform.name, inputs)}; ${prev(c, uv)}`; } else if (transform.transform.type === 'combine') { generator = (c, uv) => // combining two generated shader strings (i.e. for blend, mult, add funtions) `${generateInputs(inputs, shaderParams)(`${c}${i}`, uv)} ${prev(c, uv)} ${c} = ${shaderString(`${c}${i}`, `${c}`, transform.name, inputs)};`; } else if (transform.transform.type === 'combineCoord') { // combining two generated shader strings (i.e. for modulate functions) generator = (c, uv) => `${generateInputs(inputs, shaderParams)(`${c}${i}`, uv)} ${uv} = ${shaderString(`${c}${i}`, `${uv}`, transform.name, inputs)}; ${prev(c, uv)}`; } }); return generator; } function generateInputs(inputs, shaderParams) { let generator = (c, uv) => ''; var prev = generator; inputs.forEach((input, i) => { if (input.value.transforms) { prev = generator; generator = (c, uv) => { let ci = generateInputName(c, i); let uvi = generateInputName(`${uv}_${c}`, i); return `vec2 ${uvi} = ${uv};${prev(c, uv)} ${generateGlsl(input.value.transforms, shaderParams)(ci, uvi)}`; }; } }); return generator; } // assembles a shader string containing the arguments and the function name, i.e. 'osc(uv, frequency)' function shaderString(c, uv, method, inputs) { const str = inputs.map((input, i) => { if (input.isUniform) { return input.name; } else if (input.value && input.value.transforms) { // this by definition needs to be a generator // use the variable created for generator inputs in `generateInputs` return generateInputName(c, i); } return input.value; }).reduce((p, c) => `${p}, ${c}`, ''); return `${method}(${uv}${str})`; } // merge two arrays and remove duplicates function mergeArrays(a, b) { return a.concat(b.filter(function (item) { return a.indexOf(item) < 0; })); } // check whether array function contains(object, arr) { for (var i = 0; i < arr.length; i++) { if (object.name == arr[i].name) return true; } return false; } },{"./format-arguments.js":11,"./lib/array-utils.js":20}],13:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _glslSource = _interopRequireDefault(require("./glsl-source.js")); var _glslFunctions = _interopRequireDefault(require("./glsl/glsl-functions.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class GeneratorFactory { constructor({ defaultUniforms, defaultOutput, extendTransforms = [], changeListener = () => {} } = {}) { this.defaultOutput = defaultOutput; this.defaultUniforms = defaultUniforms; this.changeListener = changeListener; this.extendTransforms = extendTransforms; this.generators = {}; this.init(); } init() { const functions = (0, _glslFunctions.default)(); this.glslTransforms = {}; this.generators = Object.entries(this.generators).reduce((prev, [method, transform]) => { this.changeListener({ type: 'remove', synth: this, method }); return prev; }, {}); this.sourceClass = (() => { return class extends _glslSource.default {}; })(); // add user definied transforms if (Array.isArray(this.extendTransforms)) { functions.concat(this.extendTransforms); } else if (typeof this.extendTransforms === 'object' && this.extendTransforms.type) { functions.push(this.extendTransforms); } return functions.map(transform => this.setFunction(transform)); } _addMethod(method, transform) { const self = this; this.glslTransforms[method] = transform; if (transform.type === 'src') { const func = (...args) => new this.sourceClass({ name: method, transform: transform, userArgs: args, defaultOutput: this.defaultOutput, defaultUniforms: this.defaultUniforms, synth: self }); this.generators[method] = func; this.changeListener({ type: 'add', synth: this, method }); return func; } else { this.sourceClass.prototype[method] = function (...args) { this.transforms.push({ name: method, transform: transform, userArgs: args, synth: self }); return this; }; } return undefined; } setFunction(obj) { var processedGlsl = processGlsl(obj); if (processedGlsl) this._addMethod(obj.name, processedGlsl); } } const typeLookup = { 'src': { returnType: 'vec4', args: [{ type: 'vec2', name: '_st' }] }, 'coord': { returnType: 'vec2', args: [{ type: 'vec2', name: '_st' }] }, 'color': { returnType: 'vec4', args: [{ type: 'vec4', name: '_c0' }] }, 'combine': { returnType: 'vec4', args: [{ type: 'vec4', name: '_c0' }, { type: 'vec4', name: '_c1' }] }, 'combineCoord': { returnType: 'vec2', args: [{ type: 'vec2', name: '_st' }, { type: 'vec4', name: '_c0' }] } }; // expects glsl of format // { // name: 'osc', // name that will be used to access function as well as within glsl // type: 'src', // can be src: vec4(vec2 _st), coord: vec2(vec2 _st), color: vec4(vec4 _c0), combine: vec4(vec4 _c0, vec4 _c1), combineCoord: vec2(vec2 _st, vec4 _c0) // inputs: [ // { // name: 'freq', // type: 'float', // 'float' //, 'texture', 'vec4' // default: 0.2 // }, // { // name: 'sync', // type: 'float', // default: 0.1 // }, // { // name: 'offset', // type: 'float', // default: 0.0 // } // ], // glsl: ` // vec2 st = _st; // float r = sin((st.x-offset*2/freq+time*sync)*freq)*0.5 + 0.5; // float g = sin((st.x+time*sync)*freq)*0.5 + 0.5; // float b = sin((st.x+offset/freq+time*sync)*freq)*0.5 + 0.5; // return vec4(r, g, b, 1.0); // ` // } // // generates glsl function: // `vec4 osc(vec2 _st, float freq, float sync, float offset){ // vec2 st = _st; // float r = sin((st.x-offset*2/freq+time*sync)*freq)*0.5 + 0.5; // float g = sin((st.x+time*sync)*freq)*0.5 + 0.5; // float b = sin((st.x+offset/freq+time*sync)*freq)*0.5 + 0.5; // return vec4(r, g, b, 1.0); // }` function processGlsl(obj) { let t = typeLookup[obj.type]; if (t) { let inputs = t.args.concat(obj.inputs); let args = inputs.map(input => `${input.type} ${input.name}`).join(', '); // console.log('args are ', args) let glslFunction = ` ${t.returnType} ${obj.name}(${args}) { ${obj.glsl} } `; // First input gets handled specially by generator obj.inputs = inputs.slice(1); return Object.assign({}, obj, { glsl: glslFunction }); } else { console.warn(`type ${obj.type} not recognized`, obj, typeLookup); } } var _default = GeneratorFactory; exports.default = _default; },{"./glsl-source.js":14,"./glsl/glsl-functions.js":15}],14:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _generateGlsl = _interopRequireDefault(require("./generate-glsl.js")); var _utilityFunctions = _interopRequireDefault(require("./glsl/utility-functions.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // const formatArguments = require('./glsl-utils.js').formatArguments // const glslTransforms = require('./glsl/composable-glsl-functions.js') var GlslSource = function (obj) { this.transforms = []; this.transforms.push(obj); this.defaultOutput = obj.defaultOutput; this.synth = obj.synth; this.type = 'GlslSource'; this.defaultUniforms = obj.defaultUniforms; return this; }; GlslSource.prototype.addTransform = function (obj) { this.transforms.push(obj); }; GlslSource.prototype.out = function (_output) { var output = _output || this.defaultOutput; // output.renderPasses(glsl) if (output) try { var glsl = this.glsl(output); this.synth.currentFunctions = []; output.render(glsl); } catch (error) { console.warn('shader could not compile', error); } }; GlslSource.prototype.glsl = function () { //var output = _output || this.defaultOutput var self = this; // uniforms included in all shaders // this.defaultUniforms = output.uniforms var passes = []; var transforms = []; // console.log('output', output) this.transforms.forEach(transform => { if (transform.transform.type === 'renderpass') { // if (transforms.length > 0) passes.push(this.compile(transforms, output)) // transforms = [] // var uniforms = {} // const inputs = formatArguments(transform, -1) // inputs.forEach((uniform) => { uniforms[uniform.name] = uniform.value }) // // passes.push({ // frag: transform.transform.frag, // uniforms: Object.assign({}, self.defaultUniforms, uniforms) // }) // transforms.push({name: 'prev', transform: glslTransforms['prev'], synth: this.synth}) console.warn('no support for renderpass'); } else { transforms.push(transform); } }); if (transforms.length > 0) passes.push(this.compile(transforms)); return passes; }; GlslSource.prototype.compile = function (transforms) { var shaderInfo = (0, _generateGlsl.default)(transforms, this.synth); var uniforms = {}; shaderInfo.uniforms.forEach(uniform => { uniforms[uniform.name] = uniform.value; }); var frag = ` precision ${this.defaultOutput.precision} float; ${Object.values(shaderInfo.uniforms).map(uniform => { let type = uniform.type; switch (uniform.type) { case 'texture': type = 'sampler2D'; break; } return ` uniform ${type} ${uniform.name};`; }).join('')} uniform float time; uniform vec2 resolution; varying vec2 uv; uniform sampler2D prevBuffer; ${Object.values(_utilityFunctions.default).map(transform => { // console.log(transform.glsl) return ` ${transform.glsl} `; }).join('')} ${shaderInfo.glslFunctions.map(transform => { return ` ${transform.transform.glsl} `; }).join('')} void main () { vec2 st = gl_FragCoord.xy/resolution.xy; ${shaderInfo.fragColor} gl_FragColor = c; } `; return { frag: frag, uniforms: Object.assign({}, this.defaultUniforms, uniforms) }; }; var _default = GlslSource; exports.default = _default; },{"./generate-glsl.js":12,"./glsl/utility-functions.js":16}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; /* Format for adding functions to hydra. For each entry in this file, hydra automatically generates a glsl function and javascript function with the same name. You can also ass functions dynamically using setFunction(object). { name: 'osc', // name that will be used to access function in js as well as in glsl type: 'src', // can be 'src', 'color', 'combine', 'combineCoord'. see below for more info inputs: [ { name: 'freq', type: 'float', default: 0.2 }, { name: 'sync', type: 'float', default: 0.1 }, { name: 'offset', type: 'float', default: 0.0 } ], glsl: ` vec2 st = _st; float r = sin((st.x-offset*2/freq+time*sync)*freq)*0.5 + 0.5; float g = sin((st.x+time*sync)*freq)*0.5 + 0.5; float b = sin((st.x+offset/freq+time*sync)*freq)*0.5 + 0.5; return vec4(r, g, b, 1.0); ` } // The above code generates the glsl function: `vec4 osc(vec2 _st, float freq, float sync, float offset){ vec2 st = _st; float r = sin((st.x-offset*2/freq+time*sync)*freq)*0.5 + 0.5; float g = sin((st.x+time*sync)*freq)*0.5 + 0.5; float b = sin((st.x+offset/freq+time*sync)*freq)*0.5 + 0.5; return vec4(r, g, b, 1.0); }` Types and default arguments for hydra functions. The value in the 'type' field lets the parser know which type the function will be returned as well as default arguments. const types = { 'src': { returnType: 'vec4', args: [{ type: 'vec2', name: '_st' }] }, 'coord': { returnType: 'vec2', args: [{ type: 'vec2', name: '_st'}] }, 'color': { returnType: 'vec4', args: [{ type: 'vec4', name: '_c0'}] }, 'combine': { returnType: 'vec4', args: [ { type: 'vec4', name: '_c0'}, { type: 'vec4', name: '_c1'} ] }, 'combineCoord': { returnType: 'vec2', args: [ { type: 'vec2', name: '_st'}, { type: 'vec4', name: '_c0'}, ] } } */ var _default = () => [{ name: 'noise', type: 'src', inputs: [{ type: 'float', name: 'scale', default: 10 }, { type: 'float', name: 'offset', default: 0.1 }], glsl: ` return vec4(vec3(_noise(vec3(_st*scale, offset*time))), 1.0);` }, { name: 'voronoi', type: 'src', inputs: [{ type: 'float', name: 'scale', default: 5 }, { type: 'float', name: 'speed', default: 0.3 }, { type: 'float', name: 'blending', default: 0.3 }], glsl: ` vec3 color = vec3(.0); // Scale _st *= scale; // Tile the space vec2 i_st = floor(_st); vec2 f_st = fract(_st); float m_dist = 10.; // minimun distance vec2 m_point; // minimum point for (int j=-1; j<=1; j++ ) { for (int i=-1; i<=1; i++ ) { vec2 neighbor = vec2(float(i),float(j)); vec2 p = i_st + neighbor; vec2 point = fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453); point = 0.5 + 0.5*sin(time*speed + 6.2831*point); vec2 diff = neighbor + point - f_st; float dist = length(diff); if( dist < m_dist ) { m_dist = dist; m_point = point; } } } // Assign a color using the closest point position color += dot(m_point,vec2(.3,.6)); color *= 1.0 - blending*m_dist; return vec4(color, 1.0);` }, { name: 'osc', type: 'src', inputs: [{ type: 'float', name: 'frequency', default: 60 }, { type: 'float', name: 'sync', default: 0.1 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` vec2 st = _st; float r = sin((st.x-offset/frequency+time*sync)*frequency)*0.5 + 0.5; float g = sin((st.x+time*sync)*frequency)*0.5 + 0.5; float b = sin((st.x+offset/frequency+time*sync)*frequency)*0.5 + 0.5; return vec4(r, g, b, 1.0);` }, { name: 'shape', type: 'src', inputs: [{ type: 'float', name: 'sides', default: 3 }, { type: 'float', name: 'radius', default: 0.3 }, { type: 'float', name: 'smoothing', default: 0.01 }], glsl: ` vec2 st = _st * 2. - 1.; // Angle and radius from the current pixel float a = atan(st.x,st.y)+3.1416; float r = (2.*3.1416)/sides; float d = cos(floor(.5+a/r)*r-a)*length(st); return vec4(vec3(1.0-smoothstep(radius,radius + smoothing + 0.0000001,d)), 1.0);` }, { name: 'gradient', type: 'src', inputs: [{ type: 'float', name: 'speed', default: 0 }], glsl: ` return vec4(_st, sin(time*speed), 1.0);` }, { name: 'src', type: 'src', inputs: [{ type: 'sampler2D', name: 'tex', default: NaN }], glsl: ` // vec2 uv = gl_FragCoord.xy/vec2(1280., 720.); return texture2D(tex, fract(_st));` }, { name: 'solid', type: 'src', inputs: [{ type: 'float', name: 'r', default: 0 }, { type: 'float', name: 'g', default: 0 }, { type: 'float', name: 'b', default: 0 }, { type: 'float', name: 'a', default: 1 }], glsl: ` return vec4(r, g, b, a);` }, { name: 'rotate', type: 'coord', inputs: [{ type: 'float', name: 'angle', default: 10 }, { type: 'float', name: 'speed', default: 0 }], glsl: ` vec2 xy = _st - vec2(0.5); float ang = angle + speed *time; xy = mat2(cos(ang),-sin(ang), sin(ang),cos(ang))*xy; xy += 0.5; return xy;` }, { name: 'scale', type: 'coord', inputs: [{ type: 'float', name: 'amount', default: 1.5 }, { type: 'float', name: 'xMult', default: 1 }, { type: 'float', name: 'yMult', default: 1 }, { type: 'float', name: 'offsetX', default: 0.5 }, { type: 'float', name: 'offsetY', default: 0.5 }], glsl: ` vec2 xy = _st - vec2(offsetX, offsetY); xy*=(1.0/vec2(amount*xMult, amount*yMult)); xy+=vec2(offsetX, offsetY); return xy; ` }, { name: 'pixelate', type: 'coord', inputs: [{ type: 'float', name: 'pixelX', default: 20 }, { type: 'float', name: 'pixelY', default: 20 }], glsl: ` vec2 xy = vec2(pixelX, pixelY); return (floor(_st * xy) + 0.5)/xy;` }, { name: 'posterize', type: 'color', inputs: [{ type: 'float', name: 'bins', default: 3 }, { type: 'float', name: 'gamma', default: 0.6 }], glsl: ` vec4 c2 = pow(_c0, vec4(gamma)); c2 *= vec4(bins); c2 = floor(c2); c2/= vec4(bins); c2 = pow(c2, vec4(1.0/gamma)); return vec4(c2.xyz, _c0.a);` }, { name: 'shift', type: 'color', inputs: [{ type: 'float', name: 'r', default: 0.5 }, { type: 'float', name: 'g', default: 0 }, { type: 'float', name: 'b', default: 0 }, { type: 'float', name: 'a', default: 0 }], glsl: ` vec4 c2 = vec4(_c0); c2.r += fract(r); c2.g += fract(g); c2.b += fract(b); c2.a += fract(a); return vec4(c2.rgba);` }, { name: 'repeat', type: 'coord', inputs: [{ type: 'float', name: 'repeatX', default: 3 }, { type: 'float', name: 'repeatY', default: 3 }, { type: 'float', name: 'offsetX', default: 0 }, { type: 'float', name: 'offsetY', default: 0 }], glsl: ` vec2 st = _st * vec2(repeatX, repeatY); st.x += step(1., mod(st.y,2.0)) * offsetX; st.y += step(1., mod(st.x,2.0)) * offsetY; return fract(st);` }, { name: 'modulateRepeat', type: 'combineCoord', inputs: [{ type: 'float', name: 'repeatX', default: 3 }, { type: 'float', name: 'repeatY', default: 3 }, { type: 'float', name: 'offsetX', default: 0.5 }, { type: 'float', name: 'offsetY', default: 0.5 }], glsl: ` vec2 st = _st * vec2(repeatX, repeatY); st.x += step(1., mod(st.y,2.0)) + _c0.r * offsetX; st.y += step(1., mod(st.x,2.0)) + _c0.g * offsetY; return fract(st);` }, { name: 'repeatX', type: 'coord', inputs: [{ type: 'float', name: 'reps', default: 3 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` vec2 st = _st * vec2(reps, 1.0); // float f = mod(_st.y,2.0); st.y += step(1., mod(st.x,2.0))* offset; return fract(st);` }, { name: 'modulateRepeatX', type: 'combineCoord', inputs: [{ type: 'float', name: 'reps', default: 3 }, { type: 'float', name: 'offset', default: 0.5 }], glsl: ` vec2 st = _st * vec2(reps, 1.0); // float f = mod(_st.y,2.0); st.y += step(1., mod(st.x,2.0)) + _c0.r * offset; return fract(st);` }, { name: 'repeatY', type: 'coord', inputs: [{ type: 'float', name: 'reps', default: 3 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` vec2 st = _st * vec2(1.0, reps); // float f = mod(_st.y,2.0); st.x += step(1., mod(st.y,2.0))* offset; return fract(st);` }, { name: 'modulateRepeatY', type: 'combineCoord', inputs: [{ type: 'float', name: 'reps', default: 3 }, { type: 'float', name: 'offset', default: 0.5 }], glsl: ` vec2 st = _st * vec2(reps, 1.0); // float f = mod(_st.y,2.0); st.x += step(1., mod(st.y,2.0)) + _c0.r * offset; return fract(st);` }, { name: 'kaleid', type: 'coord', inputs: [{ type: 'float', name: 'nSides', default: 4 }], glsl: ` vec2 st = _st; st -= 0.5; float r = length(st); float a = atan(st.y, st.x); float pi = 2.*3.1416; a = mod(a,pi/nSides); a = abs(a-pi/nSides/2.); return r*vec2(cos(a), sin(a));` }, { name: 'modulateKaleid', type: 'combineCoord', inputs: [{ type: 'float', name: 'nSides', default: 4 }], glsl: ` vec2 st = _st - 0.5; float r = length(st); float a = atan(st.y, st.x); float pi = 2.*3.1416; a = mod(a,pi/nSides); a = abs(a-pi/nSides/2.); return (_c0.r+r)*vec2(cos(a), sin(a));` }, { name: 'scroll', type: 'coord', inputs: [{ type: 'float', name: 'scrollX', default: 0.5 }, { type: 'float', name: 'scrollY', default: 0.5 }, { type: 'float', name: 'speedX', default: 0 }, { type: 'float', name: 'speedY', default: 0 }], glsl: ` _st.x += scrollX + time*speedX; _st.y += scrollY + time*speedY; return fract(_st);` }, { name: 'scrollX', type: 'coord', inputs: [{ type: 'float', name: 'scrollX', default: 0.5 }, { type: 'float', name: 'speed', default: 0 }], glsl: ` _st.x += scrollX + time*speed; return fract(_st);` }, { name: 'modulateScrollX', type: 'combineCoord', inputs: [{ type: 'float', name: 'scrollX', default: 0.5 }, { type: 'float', name: 'speed', default: 0 }], glsl: ` _st.x += _c0.r*scrollX + time*speed; return fract(_st);` }, { name: 'scrollY', type: 'coord', inputs: [{ type: 'float', name: 'scrollY', default: 0.5 }, { type: 'float', name: 'speed', default: 0 }], glsl: ` _st.y += scrollY + time*speed; return fract(_st);` }, { name: 'modulateScrollY', type: 'combineCoord', inputs: [{ type: 'float', name: 'scrollY', default: 0.5 }, { type: 'float', name: 'speed', default: 0 }], glsl: ` _st.y += _c0.r*scrollY + time*speed; return fract(_st);` }, { name: 'add', type: 'combine', inputs: [{ type: 'float', name: 'amount', default: 1 }], glsl: ` return (_c0+_c1)*amount + _c0*(1.0-amount);` }, { name: 'sub', type: 'combine', inputs: [{ type: 'float', name: 'amount', default: 1 }], glsl: ` return (_c0-_c1)*amount + _c0*(1.0-amount);` }, { name: 'layer', type: 'combine', inputs: [], glsl: ` return vec4(mix(_c0.rgb, _c1.rgb, _c1.a), clamp(_c0.a + _c1.a, 0.0, 1.0));` }, { name: 'blend', type: 'combine', inputs: [{ type: 'float', name: 'amount', default: 0.5 }], glsl: ` return _c0*(1.0-amount)+_c1*amount;` }, { name: 'mult', type: 'combine', inputs: [{ type: 'float', name: 'amount', default: 1 }], glsl: ` return _c0*(1.0-amount)+(_c0*_c1)*amount;` }, { name: 'diff', type: 'combine', inputs: [], glsl: ` return vec4(abs(_c0.rgb-_c1.rgb), max(_c0.a, _c1.a));` }, { name: 'modulate', type: 'combineCoord', inputs: [{ type: 'float', name: 'amount', default: 0.1 }], glsl: ` // return fract(st+(_c0.xy-0.5)*amount); return _st + _c0.xy*amount;` }, { name: 'modulateScale', type: 'combineCoord', inputs: [{ type: 'float', name: 'multiple', default: 1 }, { type: 'float', name: 'offset', default: 1 }], glsl: ` vec2 xy = _st - vec2(0.5); xy*=(1.0/vec2(offset + multiple*_c0.r, offset + multiple*_c0.g)); xy+=vec2(0.5); return xy;` }, { name: 'modulatePixelate', type: 'combineCoord', inputs: [{ type: 'float', name: 'multiple', default: 10 }, { type: 'float', name: 'offset', default: 3 }], glsl: ` vec2 xy = vec2(offset + _c0.x*multiple, offset + _c0.y*multiple); return (floor(_st * xy) + 0.5)/xy;` }, { name: 'modulateRotate', type: 'combineCoord', inputs: [{ type: 'float', name: 'multiple', default: 1 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` vec2 xy = _st - vec2(0.5); float angle = offset + _c0.x * multiple; xy = mat2(cos(angle),-sin(angle), sin(angle),cos(angle))*xy; xy += 0.5; return xy;` }, { name: 'modulateHue', type: 'combineCoord', inputs: [{ type: 'float', name: 'amount', default: 1 }], glsl: ` return _st + (vec2(_c0.g - _c0.r, _c0.b - _c0.g) * amount * 1.0/resolution);` }, { name: 'invert', type: 'color', inputs: [{ type: 'float', name: 'amount', default: 1 }], glsl: ` return vec4((1.0-_c0.rgb)*amount + _c0.rgb*(1.0-amount), _c0.a);` }, { name: 'contrast', type: 'color', inputs: [{ type: 'float', name: 'amount', default: 1.6 }], glsl: ` vec4 c = (_c0-vec4(0.5))*vec4(amount) + vec4(0.5); return vec4(c.rgb, _c0.a);` }, { name: 'brightness', type: 'color', inputs: [{ type: 'float', name: 'amount', default: 0.4 }], glsl: ` return vec4(_c0.rgb + vec3(amount), _c0.a);` }, { name: 'mask', type: 'combine', inputs: [], glsl: ` float a = _luminance(_c1.rgb); return vec4(_c0.rgb*a, a*_c0.a);` }, { name: 'luma', type: 'color', inputs: [{ type: 'float', name: 'threshold', default: 0.5 }, { type: 'float', name: 'tolerance', default: 0.1 }], glsl: ` float a = smoothstep(threshold-(tolerance+0.0000001), threshold+(tolerance+0.0000001), _luminance(_c0.rgb)); return vec4(_c0.rgb*a, a);` }, { name: 'thresh', type: 'color', inputs: [{ type: 'float', name: 'threshold', default: 0.5 }, { type: 'float', name: 'tolerance', default: 0.04 }], glsl: ` return vec4(vec3(smoothstep(threshold-(tolerance+0.0000001), threshold+(tolerance+0.0000001), _luminance(_c0.rgb))), _c0.a);` }, { name: 'color', type: 'color', inputs: [{ type: 'float', name: 'r', default: 1 }, { type: 'float', name: 'g', default: 1 }, { type: 'float', name: 'b', default: 1 }, { type: 'float', name: 'a', default: 1 }], glsl: ` vec4 c = vec4(r, g, b, a); vec4 pos = step(0.0, c); // detect whether negative // if > 0, return r * _c0 // if < 0 return (1.0-r) * _c0 return vec4(mix((1.0-_c0)*abs(c), c*_c0, pos));` }, { name: 'saturate', type: 'color', inputs: [{ type: 'float', name: 'amount', default: 2 }], glsl: ` const vec3 W = vec3(0.2125, 0.7154, 0.0721); vec3 intensity = vec3(dot(_c0.rgb, W)); return vec4(mix(intensity, _c0.rgb, amount), _c0.a);` }, { name: 'hue', type: 'color', inputs: [{ type: 'float', name: 'hue', default: 0.4 }], glsl: ` vec3 c = _rgbToHsv(_c0.rgb); c.r += hue; // c.r = fract(c.r); return vec4(_hsvToRgb(c), _c0.a);` }, { name: 'colorama', type: 'color', inputs: [{ type: 'float', name: 'amount', default: 0.005 }], glsl: ` vec3 c = _rgbToHsv(_c0.rgb); c += vec3(amount); c = _hsvToRgb(c); c = fract(c); return vec4(c, _c0.a);` }, { name: 'prev', type: 'src', inputs: [], glsl: ` return texture2D(prevBuffer, fract(_st));` }, { name: 'sum', type: 'color', inputs: [{ type: 'vec4', name: 'scale', default: 1 }], glsl: ` vec4 v = _c0 * s; return v.r + v.g + v.b + v.a; } float sum(vec2 _st, vec4 s) { // vec4 is not a typo, because argument type is not overloaded vec2 v = _st.xy * s.xy; return v.x + v.y;` }, { name: 'r', type: 'color', inputs: [{ type: 'float', name: 'scale', default: 1 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` return vec4(_c0.r * scale + offset);` }, { name: 'g', type: 'color', inputs: [{ type: 'float', name: 'scale', default: 1 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` return vec4(_c0.g * scale + offset);` }, { name: 'b', type: 'color', inputs: [{ type: 'float', name: 'scale', default: 1 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` return vec4(_c0.b * scale + offset);` }, { name: 'a', type: 'color', inputs: [{ type: 'float', name: 'scale', default: 1 }, { type: 'float', name: 'offset', default: 0 }], glsl: ` return vec4(_c0.a * scale + offset);` }]; exports.default = _default; },{}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; // functions that are only used within other functions var _default = { _luminance: { type: 'util', glsl: `float _luminance(vec3 rgb){ const vec3 W = vec3(0.2125, 0.7154, 0.0721); return dot(rgb, W); }` }, _noise: { type: 'util', glsl: ` // Simplex 3D Noise // by Ian McEwan, Ashima Arts vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} float _noise(vec3 v){ const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); // First corner vec3 i = floor(v + dot(v, C.yyy) ); vec3 x0 = v - i + dot(i, C.xxx) ; // Other corners vec3 g = step(x0.yzx, x0.xyz); vec3 l = 1.0 - g; vec3 i1 = min( g.xyz, l.zxy ); vec3 i2 = max( g.xyz, l.zxy ); // x0 = x0 - 0. + 0.0 * C vec3 x1 = x0 - i1 + 1.0 * C.xxx; vec3 x2 = x0 - i2 + 2.0 * C.xxx; vec3 x3 = x0 - 1. + 3.0 * C.xxx; // Permutations i = mod(i, 289.0 ); vec4 p = permute( permute( permute( i.z + vec4(0.0, i1.z, i2.z, 1.0 )) + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); // Gradients // ( N*N points uniformly over a square, mapped onto an octahedron.) float n_ = 1.0/7.0; // N=7 vec3 ns = n_ * D.wyz - D.xzx; vec4 j = p - 49.0 * floor(p * ns.z *ns.z); // mod(p,N*N) vec4 x_ = floor(j * ns.z); vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) vec4 x = x_ *ns.x + ns.yyyy; vec4 y = y_ *ns.x + ns.yyyy; vec4 h = 1.0 - abs(x) - abs(y); vec4 b0 = vec4( x.xy, y.xy ); vec4 b1 = vec4( x.zw, y.zw ); vec4 s0 = floor(b0)*2.0 + 1.0; vec4 s1 = floor(b1)*2.0 + 1.0; vec4 sh = -step(h, vec4(0.0)); vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; vec3 p0 = vec3(a0.xy,h.x); vec3 p1 = vec3(a0.zw,h.y); vec3 p2 = vec3(a1.xy,h.z); vec3 p3 = vec3(a1.zw,h.w); //Normalise gradients vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w; // Mix final noise value vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); m = m * m; return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) ); } ` }, _rgbToHsv: { type: 'util', glsl: `vec3 _rgbToHsv(vec3 c){ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); float d = q.x - min(q.w, q.y); float e = 1.0e-10; return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); }` }, _hsvToRgb: { type: 'util', glsl: `vec3 _hsvToRgb(vec3 c){ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); }` } }; exports.default = _default; },{}],17:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _webcam = _interopRequireDefault(require("./lib/webcam.js")); var _screenmedia = _interopRequireDefault(require("./lib/screenmedia.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class HydraSource { constructor({ regl, width, height, pb, label = "" }) { this.label = label; this.regl = regl; this.src = null; this.dynamic = true; this.width = width; this.height = height; this.tex = this.regl.texture({ // shape: [width, height] shape: [1, 1] }); this.pb = pb; } init(opts, params) { if ('src' in opts) { this.src = opts.src; this.tex = this.regl.texture({ data: this.src, ...params }); } if ('dynamic' in opts) this.dynamic = opts.dynamic; } initCam(index, params) { const self = this; (0, _webcam.default)(index).then(response => { self.src = response.video; self.dynamic = true; self.tex = self.regl.texture({ data: self.src, ...params }); }).catch(err => console.log('could not get camera', err)); } initVideo(url = '', params) { // const self = this const vid = document.createElement('video'); vid.crossOrigin = 'anonymous'; vid.autoplay = true; vid.loop = true; vid.muted = true; // mute in order to load without user interaction const onload = vid.addEventListener('loadeddata', () => { this.src = vid; vid.play(); this.tex = this.regl.texture({ data: this.src, ...params }); this.dynamic = true; }); vid.src = url; } initImage(url = '', params) { const img = document.createElement('img'); img.crossOrigin = 'anonymous'; img.src = url; img.onload = () => { this.src = img; this.dynamic = false; this.tex = this.regl.texture({ data: this.src, ...params }); }; } initStream(streamName, params) { // console.log("initing stream!", streamName) let self = this; if (streamName && this.pb) { this.pb.initSource(streamName); this.pb.on('got video', function (nick, video) { if (nick === streamName) { self.src = video; self.dynamic = true; self.tex = self.regl.texture({ data: self.src, ...params }); } }); } } // index only relevant in atom-hydra + desktop apps initScreen(index = 0, params) { const self = this; (0, _screenmedia.default)().then(function (response) { self.src = response.video; self.tex = self.regl.texture({ data: self.src, ...params }); self.dynamic = true; // console.log("received screen input") }).catch(err => console.log('could not get screen', err)); } // cache for the canvases, so we don't create them every time canvases = {}; // Creates a canvas and returns the 2d context initCanvas(width = 1000, height = 1000) { if (this.canvases[this.label] == undefined) { const canvas = document.createElement("canvas"); const ctx = canvas.getContext('2d'); if (ctx != null) this.canvases[this.label] = ctx; } const ctx = this.canvases[this.label]; const canvas = ctx.canvas; if (canvas.width !== width && canvas.height !== height) { canvas.width = width; canvas.height = height; } else { ctx.clearRect(0, 0, width, height); } this.init({ src: canvas }); this.dynamic = true; return ctx; } resize(width, height) { this.width = width; this.height = height; } clear() { if (this.src && this.src.srcObject) { if (this.src.srcObject.getTracks) { this.src.srcObject.getTracks().forEach(track => track.stop()); } } this.src = null; this.tex = this.regl.texture({ shape: [1, 1] }); } tick(time) { // console.log(this.src, this.tex.width, this.tex.height) if (this.src && this.dynamic === true) { if (this.src.videoWidth && this.src.videoWidth !== this.tex.width) { console.log(this.src.videoWidth, this.src.videoHeight, this.tex.width, this.tex.height); this.tex.resize(this.src.videoWidth, this.src.videoHeight); } if (this.src.width && this.src.width !== this.tex.width) { this.tex.resize(this.src.width, this.src.height); } this.tex.subimage(this.src); } } getTexture() { return this.tex; } } var _default = HydraSource; exports.default = _default; },{"./lib/screenmedia.js":26,"./lib/webcam.js":28}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _output = _interopRequireDefault(require("./output.js")); var _rafLoop = _interopRequireDefault(require("raf-loop")); var _hydraSource = _interopRequireDefault(require("./hydra-source.js")); var _mouse = _interopRequireDefault(require("./lib/mouse.js")); var _audio = _interopRequireDefault(require("./lib/audio.js")); var _videoRecorder = _interopRequireDefault(require("./lib/video-recorder.js")); var _arrayUtils = _interopRequireDefault(require("./lib/array-utils.js")); var _evalSandbox = _interopRequireDefault(require("./eval-sandbox.js")); var _generatorFactory = _interopRequireDefault(require("./generator-factory.js")); var _regl = _interopRequireDefault(require("regl")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // import strudel from './lib/strudel.js' // const window = global.window const Mouse = (0, _mouse.default)(); // to do: add ability to pass in certain uniforms and transforms class HydraRenderer { constructor({ pb = null, width = 1280, height = 720, numSources = 4, numOutputs = 4, makeGlobal = true, autoLoop = true, detectAudio = true, enableStreamCapture = true, canvas, precision, extendTransforms = {} // add your own functions on init } = {}) { _arrayUtils.default.init(); this.pb = pb; this.width = width; this.height = height; this.renderAll = false; this.detectAudio = detectAudio; this._initCanvas(canvas); //global.window.test = 'hi' // object that contains all properties that will be made available on the global context and during local evaluation this.synth = { time: 0, bpm: 30, width: this.width, height: this.height, fps: undefined, stats: { fps: 0 }, speed: 1, mouse: Mouse, render: this._render.bind(this), setResolution: this.setResolution.bind(this), update: dt => {}, // user defined update function afterUpdate: dt => {}, // user defined function run after update hush: this.hush.bind(this), tick: this.tick.bind(this) }; if (makeGlobal) window.loadScript = this.loadScript; this.timeSinceLastUpdate = 0; this._time = 0; // for internal use, only to use for deciding when to render frames // only allow valid precision options let precisionOptions = ['lowp', 'mediump', 'highp']; if (precision && precisionOptions.includes(precision.toLowerCase())) { this.precision = precision.toLowerCase(); // // if(!precisionValid){ // console.warn('[hydra-synth warning]\nConstructor was provided an invalid floating point precision value of "' + precision + '". Using default value of "mediump" instead.') // } } else { let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) || navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) && !window.MSStream; this.precision = isIOS ? 'highp' : 'mediump'; } this.extendTransforms = extendTransforms; // boolean to store when to save screenshot this.saveFrame = false; // if stream capture is enabled, this object contains the capture stream this.captureStream = null; this.generator = undefined; this._initRegl(); this._initOutputs(numOutputs); this._initSources(numSources); this._generateGlslTransforms(); this.synth.screencap = () => { this.saveFrame = true; }; if (enableStreamCapture) { try { this.captureStream = this.canvas.captureStream(25); // to do: enable capture stream of specific sources and outputs this.synth.vidRecorder = new _videoRecorder.default(this.captureStream); } catch (e) { console.warn('[hydra-synth warning]\nnew MediaSource() is not currently supported on iOS.'); console.error(e); } } if (detectAudio) this._initAudio(); if (autoLoop) (0, _rafLoop.default)(this.tick.bind(this)).start(); // final argument is properties that the user can set, all others are treated as read-only this.sandbox = new _evalSandbox.default(this.synth, makeGlobal, ['speed', 'update', 'afterUpdate', 'bpm', 'fps']); } eval(code) { this.sandbox.eval(code); } getScreenImage(callback) { this.imageCallback = callback; this.saveFrame = true; } hush() { this.s.forEach(source => { source.clear(); }); this.o.forEach(output => { this.synth.solid(0, 0, 0, 0).out(output); }); this.synth.render(this.o[0]); // this.synth.update = (dt) => {} this.sandbox.set('update', dt => {}); this.sandbox.set('afterUpdate', dt => {}); } loadScript(url = "") { const p = new Promise((res, rej) => { var script = document.createElement("script"); script.onload = function () { console.log(`loaded script ${url}`); res(); }; script.onerror = err => { console.log(`error loading script ${url}`, "log-error"); res(); }; script.src = url; document.head.appendChild(script); }); return p; } setResolution(width, height) { // console.log(width, height) this.canvas.width = width; this.canvas.height = height; this.width = width; // is this necessary? this.height = height; // ? this.sandbox.set('width', width); this.sandbox.set('height', height); console.log(this.width); this.o.forEach(output => { output.resize(width, height); }); this.s.forEach(source => { source.resize(width, height); }); this.regl._refresh(); console.log(this.canvas.width); } canvasToImage(callback) { const a = document.createElement('a'); a.style.display = 'none'; let d = new Date(); a.download = `hydra-${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}-${d.getHours()}.${d.getMinutes()}.${d.getSeconds()}.png`; document.body.appendChild(a); var self = this; this.canvas.toBlob(blob => { if (self.imageCallback) { self.imageCallback(blob); delete self.imageCallback; } else { a.href = URL.createObjectURL(blob); console.log(a.href); a.click(); } }, 'image/png'); setTimeout(() => { document.body.removeChild(a); window.URL.revokeObjectURL(a.href); }, 300); } _initAudio() { const that = this; this.synth.a = new _audio.default({ numBins: 4, parentEl: this.canvas.parentNode // changeListener: ({audio}) => { // that.a = audio.bins.map((_, index) => // (scale = 1, offset = 0) => () => (audio.fft[index] * scale + offset) // ) // // if (that.makeGlobal) { // that.a.forEach((a, index) => { // const aname = `a${index}` // window[aname] = a // }) // } // } }); } // create main output canvas and add to screen _initCanvas(canvas) { if (canvas) { this.canvas = canvas; this.width = canvas.width; this.height = canvas.height; } else { this.canvas = document.createElement('canvas'); this.canvas.width = this.width; this.canvas.height = this.height; this.canvas.style.width = '100%'; this.canvas.style.height = '100%'; this.canvas.style.imageRendering = 'pixelated'; document.body.appendChild(this.canvas); } } _initRegl() { this.regl = (0, _regl.default)({ // profile: true, canvas: this.canvas, pixelRatio: 1 //, // extensions: [ // 'oes_texture_half_float', // 'oes_texture_half_float_linear' // ], // optionalExtensions: [ // 'oes_texture_float', // 'oes_texture_float_linear' //] }); // This clears the color buffer to black and the depth buffer to 1 this.regl.clear({ color: [0, 0, 0, 1] }); this.renderAll = this.regl({ frag: ` precision ${this.precision} float; varying vec2 uv; uniform sampler2D tex0; uniform sampler2D tex1; uniform sampler2D tex2; uniform sampler2D tex3; void main () { vec2 st = vec2(1.0 - uv.x, uv.y); st*= vec2(2); vec2 q = floor(st).xy*(vec2(2.0, 1.0)); int quad = int(q.x) + int(q.y); st.x += step(1., mod(st.y,2.0)); st.y += step(1., mod(st.x,2.0)); st = fract(st); if(quad==0){ gl_FragColor = texture2D(tex0, st); } else if(quad==1){ gl_FragColor = texture2D(tex1, st); } else if (quad==2){ gl_FragColor = texture2D(tex2, st); } else { gl_FragColor = texture2D(tex3, st); } } `, vert: ` precision ${this.precision} float; attribute vec2 position; varying vec2 uv; void main () { uv = position; gl_Position = vec4(1.0 - 2.0 * position, 0, 1); }`, attributes: { position: [[-2, 0], [0, -2], [2, 2]] }, uniforms: { tex0: this.regl.prop('tex0'), tex1: this.regl.prop('tex1'), tex2: this.regl.prop('tex2'), tex3: this.regl.prop('tex3') }, count: 3, depth: { enable: false } }); this.renderFbo = this.regl({ frag: ` precision ${this.precision} float; varying vec2 uv; uniform vec2 resolution; uniform sampler2D tex0; void main () { gl_FragColor = texture2D(tex0, vec2(1.0 - uv.x, uv.y)); } `, vert: ` precision ${this.precision} float; attribute vec2 position; varying vec2 uv; void main () { uv = position; gl_Position = vec4(1.0 - 2.0 * position, 0, 1); }`, attributes: { position: [[-2, 0], [0, -2], [2, 2]] }, uniforms: { tex0: this.regl.prop('tex0'), resolution: this.regl.prop('resolution') }, count: 3, depth: { enable: false } }); } _initOutputs(numOutputs) { const self = this; this.o = Array(numOutputs).fill().map((el, index) => { var o = new _output.default({ regl: this.regl, width: this.width, height: this.height, precision: this.precision, label: `o${index}` }); // o.render() o.id = index; self.synth['o' + index] = o; return o; }); // set default output this.output = this.o[0]; } _initSources(numSources) { this.s = []; for (var i = 0; i < numSources; i++) { this.createSource(i); } } createSource(i) { let s = new _hydraSource.default({ regl: this.regl, pb: this.pb, width: this.width, height: this.height, label: `s${i}` }); this.synth['s' + this.s.length] = s; this.s.push(s); return s; } _generateGlslTransforms() { var self = this; this.generator = new _generatorFactory.default({ defaultOutput: this.o[0], defaultUniforms: this.o[0].uniforms, extendTransforms: this.extendTransforms, changeListener: ({ type, method, synth }) => { if (type === 'add') { self.synth[method] = synth.generators[method]; if (self.sandbox) self.sandbox.add(method); } else if (type === 'remove') {// what to do here? dangerously deleting window methods //delete window[method] } // } } }); this.synth.setFunction = this.generator.setFunction.bind(this.generator); } _render(output) { if (output) { this.output = output; this.isRenderingAll = false; } else { this.isRenderingAll = true; } } // dt in ms tick(dt, uniforms) { try { this.sandbox.tick(); if (this.detectAudio === true) this.synth.a.tick(); // let updateInterval = 1000/this.synth.fps // ms this.sandbox.set('time', this.synth.time += dt * 0.001 * this.synth.speed); this.timeSinceLastUpdate += dt; if (!this.synth.fps || this.timeSinceLastUpdate >= 1000 / this.synth.fps) { // console.log(1000/this.timeSinceLastUpdate) this.synth.stats.fps = Math.ceil(1000 / this.timeSinceLastUpdate); if (this.synth.update) { try { this.synth.update(this.timeSinceLastUpdate); } catch (e) { console.log(e); } } // console.log(this.synth.speed, this.synth.time) for (let i = 0; i < this.s.length; i++) { this.s[i].tick(this.synth.time); } // console.log(this.canvas.width, this.canvas.height) const currentTime = this.synth.time; for (let i = 0; i < this.o.length; i++) { this.o[i].tick({ time: currentTime, mouse: this.synth.mouse, bpm: this.synth.bpm, resolution: [this.canvas.width, this.canvas.height] }); } if (this.isRenderingAll) { this.renderAll({ tex0: this.o[0].getCurrent(), tex1: this.o[1].getCurrent(), tex2: this.o[2].getCurrent(), tex3: this.o[3].getCurrent(), resolution: [this.canvas.width, this.canvas.height] }); } else { this.renderFbo({ tex0: this.output.getCurrent(), resolution: [this.canvas.width, this.canvas.height] }); } if (this.synth.afterUpdate) { try { this.synth.afterUpdate(this.timeSinceLastUpdate); } catch (e) { console.log(e); } } this.timeSinceLastUpdate = 0; } if (this.saveFrame === true) { this.canvasToImage(); this.saveFrame = false; } } catch (e) { console.warn('Error during tick():', e); // this.regl.poll() } } } var _default = HydraRenderer; exports.default = _default; },{"./eval-sandbox.js":10,"./generator-factory.js":13,"./hydra-source.js":17,"./lib/array-utils.js":20,"./lib/audio.js":21,"./lib/mouse.js":24,"./lib/video-recorder.js":27,"./output.js":29,"raf-loop":6,"regl":8}],19:[function(require,module,exports){ "use strict"; var _hydraSynth = _interopRequireDefault(require("./hydra-synth.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } //import ShaderGenerator = require('./shader-generator.js') // alert('hi') // export default Synth module.exports = _hydraSynth.default; },{"./hydra-synth.js":18}],20:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _easingFunctions = _interopRequireDefault(require("./easing-functions.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // WIP utils for working with arrays // Possibly should be integrated with lfo extension, etc. // to do: transform time rather than array values, similar to working with coordinates in hydra var map = (num, in_min, in_max, out_min, out_max) => { return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }; // The '%' operator is a remainder operator, and Javascript lacks a dedicated // modulo operator. This function is an implementation of the operation // copied-n-pasted from // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder#description var modulo = (n, d) => { return (n % d + d) % d; }; var _default = { init: () => { Array.prototype.fast = function (speed = 1) { this._speed = speed; return this; }; Array.prototype.smooth = function (smooth = 1) { this._smooth = smooth; return this; }; Array.prototype.ease = function (ease = 'linear') { if (typeof ease == 'function') { this._smooth = 1; this._ease = ease; } else if (_easingFunctions.default[ease]) { this._smooth = 1; this._ease = _easingFunctions.default[ease]; } return this; }; Array.prototype.offset = function (offset = 0.5) { this._offset = offset % 1.0; return this; }; // Array.prototype.bounce = function() { // this.modifiers.bounce = true // return this // } Array.prototype.fit = function (low = 0, high = 1) { let lowest = Math.min(...this); let highest = Math.max(...this); var newArr = this.map(num => map(num, lowest, highest, low, high)); newArr._speed = this._speed; newArr._smooth = this._smooth; newArr._ease = this._ease; return newArr; }; }, getValue: (arr = []) => ({ time, bpm }) => { let speed = arr._speed ? arr._speed : 1; let smooth = arr._smooth ? arr._smooth : 0; let index = time * speed * (bpm / 60) + (arr._offset || 0); if (smooth !== 0) { let ease = arr._ease ? arr._ease : _easingFunctions.default['linear']; let _index = index - smooth / 2; // Compute the first value used for the interpolation: wrap _index inside the range [0, arr.length), then round the resulting value towards 0. // Note that, during the first seconds Hydra is running, _index may assume a negative value. // If we wrapped _index inside the range [0, arr.length) using the regular remainder operator, the result would be negative. // Passing a negative index to an array returns undefined, which ultimately causes a number of graphical glitches. // We need to use the modulo operation to prevent this. let currValue = arr[Math.floor(modulo(_index, arr.length))]; // Compute the second value used for the interpolation, in a similar fashion to 'currValue'. // The above reasoning about the choice of the modulo operation applies for 'nextValue', too. let nextValue = arr[Math.floor(modulo(_index + 1, arr.length))]; // Compute the time parameter for the interpolation. // Note that, during the first seconds Hydra is running, _index may assume a negative value. // Assuming 'smooth' is positive, if we wrapped _index in the range [0, 1) using the regular remainder operator, t would become negative as a result. // This would cause the final interpolation to assume values inconsistent with the later ones. // E.g. [0, 1].smooth() should always generate values between 0 and 1, but the initial values would be negative. // We need to use the modulo operation to prevent this. let t = Math.min(modulo(_index, 1) / smooth, 1); return ease(t) * (nextValue - currValue) + currValue; } else { const val = arr[Math.floor(index % arr.length)]; return arr[Math.floor(index % arr.length)]; } } }; exports.default = _default; },{"./easing-functions.js":22}],21:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _meyda = _interopRequireDefault(require("meyda")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class Audio { constructor({ numBins = 4, cutoff = 2, smooth = 0.4, max = 15, scale = 10, isDrawing = false, parentEl = document.body }) { this.vol = 0; this.scale = scale; this.max = max; this.cutoff = cutoff; this.smooth = smooth; this.setBins(numBins); // beat detection from: https://github.com/therewasaguy/p5-music-viz/blob/gh-pages/demos/01d_beat_detect_amplitude/sketch.js this.beat = { holdFrames: 20, threshold: 40, _cutoff: 0, // adaptive based on sound state decay: 0.98, _framesSinceBeat: 0 // keeps track of frames }; this.onBeat = () => {// console.log("beat") }; this.canvas = document.createElement('canvas'); this.canvas.width = 100; this.canvas.height = 80; this.canvas.style.width = "100px"; this.canvas.style.height = "80px"; this.canvas.style.position = 'absolute'; this.canvas.style.right = '0px'; this.canvas.style.bottom = '0px'; parentEl.appendChild(this.canvas); this.isDrawing = isDrawing; this.ctx = this.canvas.getContext('2d'); this.ctx.fillStyle = "#DFFFFF"; this.ctx.strokeStyle = "#0ff"; this.ctx.lineWidth = 0.5; if (window.navigator.mediaDevices) { window.navigator.mediaDevices.getUserMedia({ video: false, audio: true }).then(stream => { // console.log('got mic stream', stream) this.stream = stream; this.context = new AudioContext(); // this.context = new AudioContext() let audio_stream = this.context.createMediaStreamSource(stream); // console.log(this.context) this.meyda = _meyda.default.createMeydaAnalyzer({ audioContext: this.context, source: audio_stream, featureExtractors: ['loudness' // 'perceptualSpread', // 'perceptualSharpness', // 'spectralCentroid' ] }); }).catch(err => console.log('ERROR', err)); } } detectBeat(level) { //console.log(level, this.beat._cutoff) if (level > this.beat._cutoff && level > this.beat.threshold) { this.onBeat(); this.beat._cutoff = level * 1.2; this.beat._framesSinceBeat = 0; } else { if (this.beat._framesSinceBeat <= this.beat.holdFrames) { this.beat._framesSinceBeat++; } else { this.beat._cutoff *= this.beat.decay; this.beat._cutoff = Math.max(this.beat._cutoff, this.beat.threshold); } } } tick() { if (this.meyda) { var features = this.meyda.get(); if (features && features !== null) { this.vol = features.loudness.total; this.detectBeat(this.vol); // reduce loudness array to number of bins const reducer = (accumulator, currentValue) => accumulator + currentValue; let spacing = Math.floor(features.loudness.specific.length / this.bins.length); this.prevBins = this.bins.slice(0); this.bins = this.bins.map((bin, index) => { return features.loudness.specific.slice(index * spacing, (index + 1) * spacing).reduce(reducer); }).map((bin, index) => { // map to specified range // return (bin * (1.0 - this.smooth) + this.prevBins[index] * this.smooth) return bin * (1.0 - this.settings[index].smooth) + this.prevBins[index] * this.settings[index].smooth; }); // var y = this.canvas.height - scale*this.settings[index].cutoff // this.ctx.beginPath() // this.ctx.moveTo(index*spacing, y) // this.ctx.lineTo((index+1)*spacing, y) // this.ctx.stroke() // // var yMax = this.canvas.height - scale*(this.settings[index].scale + this.settings[index].cutoff) this.fft = this.bins.map((bin, index) => // Math.max(0, (bin - this.cutoff) / (this.max - this.cutoff)) Math.max(0, (bin - this.settings[index].cutoff) / this.settings[index].scale)); if (this.isDrawing) this.draw(); } } } setCutoff(cutoff) { this.cutoff = cutoff; this.settings = this.settings.map(el => { el.cutoff = cutoff; return el; }); } setSmooth(smooth) { this.smooth = smooth; this.settings = this.settings.map(el => { el.smooth = smooth; return el; }); } setBins(numBins) { this.bins = Array(numBins).fill(0); this.prevBins = Array(numBins).fill(0); this.fft = Array(numBins).fill(0); this.settings = Array(numBins).fill(0).map(() => ({ cutoff: this.cutoff, scale: this.scale, smooth: this.smooth })); // to do: what to do in non-global mode? this.bins.forEach((bin, index) => { window['a' + index] = (scale = 1, offset = 0) => () => a.fft[index] * scale + offset; }); // console.log(this.settings) } setScale(scale) { this.scale = scale; this.settings = this.settings.map(el => { el.scale = scale; return el; }); } setMax(max) { this.max = max; console.log('set max is deprecated'); } hide() { this.isDrawing = false; this.canvas.style.display = 'none'; } show() { this.isDrawing = true; this.canvas.style.display = 'block'; } draw() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); var spacing = this.canvas.width / this.bins.length; var scale = this.canvas.height / (this.max * 2); // console.log(this.bins) this.bins.forEach((bin, index) => { var height = bin * scale; this.ctx.fillRect(index * spacing, this.canvas.height - height, spacing, height); // console.log(this.settings[index]) var y = this.canvas.height - scale * this.settings[index].cutoff; this.ctx.beginPath(); this.ctx.moveTo(index * spacing, y); this.ctx.lineTo((index + 1) * spacing, y); this.ctx.stroke(); var yMax = this.canvas.height - scale * (this.settings[index].scale + this.settings[index].cutoff); this.ctx.beginPath(); this.ctx.moveTo(index * spacing, yMax); this.ctx.lineTo((index + 1) * spacing, yMax); this.ctx.stroke(); }); /*var y = this.canvas.height - scale*this.cutoff this.ctx.beginPath() this.ctx.moveTo(0, y) this.ctx.lineTo(this.canvas.width, y) this.ctx.stroke() var yMax = this.canvas.height - scale*this.max this.ctx.beginPath() this.ctx.moveTo(0, yMax) this.ctx.lineTo(this.canvas.width, yMax) this.ctx.stroke()*/ } } var _default = Audio; exports.default = _default; },{"meyda":3}],22:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; // from https://gist.github.com/gre/1650294 var _default = { // no easing, no acceleration linear: function (t) { return t; }, // accelerating from zero velocity easeInQuad: function (t) { return t * t; }, // decelerating to zero velocity easeOutQuad: function (t) { return t * (2 - t); }, // acceleration until halfway, then deceleration easeInOutQuad: function (t) { return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t; }, // accelerating from zero velocity easeInCubic: function (t) { return t * t * t; }, // decelerating to zero velocity easeOutCubic: function (t) { return --t * t * t + 1; }, // acceleration until halfway, then deceleration easeInOutCubic: function (t) { return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; }, // accelerating from zero velocity easeInQuart: function (t) { return t * t * t * t; }, // decelerating to zero velocity easeOutQuart: function (t) { return 1 - --t * t * t * t; }, // acceleration until halfway, then deceleration easeInOutQuart: function (t) { return t < .5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t; }, // accelerating from zero velocity easeInQuint: function (t) { return t * t * t * t * t; }, // decelerating to zero velocity easeOutQuint: function (t) { return 1 + --t * t * t * t * t; }, // acceleration until halfway, then deceleration easeInOutQuint: function (t) { return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t; }, // sin shape sin: function (t) { return (1 + Math.sin(Math.PI * t - Math.PI / 2)) / 2; } }; exports.default = _default; },{}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; // https://github.com/mikolalysenko/mouse-event const mouse = {}; function mouseButtons(ev) { if (typeof ev === 'object') { if ('buttons' in ev) { return ev.buttons; } else if ('which' in ev) { var b = ev.which; if (b === 2) { return 4; } else if (b === 3) { return 2; } else if (b > 0) { return 1 << b - 1; } } else if ('button' in ev) { var b = ev.button; if (b === 1) { return 4; } else if (b === 2) { return 2; } else if (b >= 0) { return 1 << b; } } } return 0; } mouse.buttons = mouseButtons; function mouseElement(ev) { return ev.target || ev.srcElement || window; } mouse.element = mouseElement; function mouseRelativeX(ev) { if (typeof ev === 'object') { if ('pageX' in ev) { return ev.pageX; } } return 0; } mouse.x = mouseRelativeX; function mouseRelativeY(ev) { if (typeof ev === 'object') { if ('pageY' in ev) { return ev.pageY; } } return 0; } mouse.y = mouseRelativeY; var _default = mouse; exports.default = _default; },{}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _mouseEvent = _interopRequireDefault(require("./mouse-event.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // based on https://github.com/mikolalysenko/mouse-change var _default = mouseListen; exports.default = _default; function mouseListen(element, callback) { if (!callback) { callback = element; element = window; } var buttonState = 0; var x = 0; var y = 0; var mods = { shift: false, alt: false, control: false, meta: false }; var attached = false; function updateMods(ev) { var changed = false; if ('altKey' in ev) { changed = changed || ev.altKey !== mods.alt; mods.alt = !!ev.altKey; } if ('shiftKey' in ev) { changed = changed || ev.shiftKey !== mods.shift; mods.shift = !!ev.shiftKey; } if ('ctrlKey' in ev) { changed = changed || ev.ctrlKey !== mods.control; mods.control = !!ev.ctrlKey; } if ('metaKey' in ev) { changed = changed || ev.metaKey !== mods.meta; mods.meta = !!ev.metaKey; } return changed; } function handleEvent(nextButtons, ev) { var nextX = _mouseEvent.default.x(ev); var nextY = _mouseEvent.default.y(ev); if ('buttons' in ev) { nextButtons = ev.buttons | 0; } if (nextButtons !== buttonState || nextX !== x || nextY !== y || updateMods(ev)) { buttonState = nextButtons | 0; x = nextX || 0; y = nextY || 0; callback && callback(buttonState, x, y, mods); } } function clearState(ev) { handleEvent(0, ev); } function handleBlur() { if (buttonState || x || y || mods.shift || mods.alt || mods.meta || mods.control) { x = y = 0; buttonState = 0; mods.shift = mods.alt = mods.control = mods.meta = false; callback && callback(0, 0, 0, mods); } } function handleMods(ev) { if (updateMods(ev)) { callback && callback(buttonState, x, y, mods); } } function handleMouseMove(ev) { if (_mouseEvent.default.buttons(ev) === 0) { handleEvent(0, ev); } else { handleEvent(buttonState, ev); } } function handleMouseDown(ev) { handleEvent(buttonState | _mouseEvent.default.buttons(ev), ev); } function handleMouseUp(ev) { handleEvent(buttonState & ~_mouseEvent.default.buttons(ev), ev); } function attachListeners() { if (attached) { return; } attached = true; element.addEventListener('mousemove', handleMouseMove); element.addEventListener('mousedown', handleMouseDown); element.addEventListener('mouseup', handleMouseUp); element.addEventListener('mouseleave', clearState); element.addEventListener('mouseenter', clearState); element.addEventListener('mouseout', clearState); element.addEventListener('mouseover', clearState); element.addEventListener('blur', handleBlur); element.addEventListener('keyup', handleMods); element.addEventListener('keydown', handleMods); element.addEventListener('keypress', handleMods); if (element !== window) { window.addEventListener('blur', handleBlur); window.addEventListener('keyup', handleMods); window.addEventListener('keydown', handleMods); window.addEventListener('keypress', handleMods); } } function detachListeners() { if (!attached) { return; } attached = false; element.removeEventListener('mousemove', handleMouseMove); element.removeEventListener('mousedown', handleMouseDown); element.removeEventListener('mouseup', handleMouseUp); element.removeEventListener('mouseleave', clearState); element.removeEventListener('mouseenter', clearState); element.removeEventListener('mouseout', clearState); element.removeEventListener('mouseover', clearState); element.removeEventListener('blur', handleBlur); element.removeEventListener('keyup', handleMods); element.removeEventListener('keydown', handleMods); element.removeEventListener('keypress', handleMods); if (element !== window) { window.removeEventListener('blur', handleBlur); window.removeEventListener('keyup', handleMods); window.removeEventListener('keydown', handleMods); window.removeEventListener('keypress', handleMods); } } // Attach listeners attachListeners(); var result = { element: element }; Object.defineProperties(result, { enabled: { get: function () { return attached; }, set: function (f) { if (f) { attachListeners(); } else { detachListeners(); } }, enumerable: true }, buttons: { get: function () { return buttonState; }, enumerable: true }, x: { get: function () { return x; }, enumerable: true }, y: { get: function () { return y; }, enumerable: true }, mods: { get: function () { return mods; }, enumerable: true } }); return result; } },{"./mouse-event.js":23}],25:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; // attempt custom evaluation sandbox for hydra functions // for now, just avoids polluting the global namespace // should probably be replaced with an abstract syntax tree var _default = parent => { var initialCode = ``; var sandbox = createSandbox(initialCode); var addToContext = (name, object) => { initialCode += ` var ${name} = ${object} `; sandbox = createSandbox(initialCode); }; return { addToContext: addToContext, eval: code => sandbox.eval(code) }; function createSandbox(initial) { globalThis.eval(initial); // optional params var localEval = function (code) { globalThis.eval(code); }; // API/data for end-user return { eval: localEval }; } }; exports.default = _default; },{}],26:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _default; function _default(options) { return new Promise(function (resolve, reject) { // async function startCapture(displayMediaOptions) { navigator.mediaDevices.getDisplayMedia(options).then(stream => { const video = document.createElement('video'); video.srcObject = stream; video.addEventListener('loadedmetadata', () => { video.play(); resolve({ video: video }); }); }).catch(err => reject(err)); }); } },{}],27:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; class VideoRecorder { constructor(stream) { this.mediaSource = new MediaSource(); this.stream = stream; // testing using a recording as input this.output = document.createElement('video'); this.output.autoplay = true; this.output.loop = true; let self = this; this.mediaSource.addEventListener('sourceopen', () => { console.log('MediaSource opened'); self.sourceBuffer = self.mediaSource.addSourceBuffer('video/webm; codecs="vp8"'); console.log('Source buffer: ', sourceBuffer); }); } start() { // let options = {mimeType: 'video/webm'}; // let options = {mimeType: 'video/webm;codecs=h264'}; let options = { mimeType: 'video/webm;codecs=vp9' }; this.recordedBlobs = []; try { this.mediaRecorder = new MediaRecorder(this.stream, options); } catch (e0) { console.log('Unable to create MediaRecorder with options Object: ', e0); try { options = { mimeType: 'video/webm,codecs=vp9' }; this.mediaRecorder = new MediaRecorder(this.stream, options); } catch (e1) { console.log('Unable to create MediaRecorder with options Object: ', e1); try { options = 'video/vp8'; // Chrome 47 this.mediaRecorder = new MediaRecorder(this.stream, options); } catch (e2) { alert('MediaRecorder is not supported by this browser.\n\n' + 'Try Firefox 29 or later, or Chrome 47 or later, ' + 'with Enable experimental Web Platform features enabled from chrome://flags.'); console.error('Exception while creating MediaRecorder:', e2); return; } } } console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options); this.mediaRecorder.onstop = this._handleStop.bind(this); this.mediaRecorder.ondataavailable = this._handleDataAvailable.bind(this); this.mediaRecorder.start(100); // collect 100ms of data console.log('MediaRecorder started', this.mediaRecorder); } stop() { this.mediaRecorder.stop(); } _handleStop() { //const superBuffer = new Blob(recordedBlobs, {type: 'video/webm'}) // const blob = new Blob(this.recordedBlobs, {type: 'video/webm;codecs=h264'}) const blob = new Blob(this.recordedBlobs, { type: this.mediaRecorder.mimeType }); const url = window.URL.createObjectURL(blob); this.output.src = url; const a = document.createElement('a'); a.style.display = 'none'; a.href = url; let d = new Date(); a.download = `hydra-${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}-${d.getHours()}.${d.getMinutes()}.${d.getSeconds()}.webm`; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 300); } _handleDataAvailable(event) { if (event.data && event.data.size > 0) { this.recordedBlobs.push(event.data); } } } var _default = VideoRecorder; exports.default = _default; },{}],28:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _default; //const enumerateDevices = require('enumerate-devices') function _default(deviceId) { return navigator.mediaDevices.enumerateDevices().then(devices => devices.filter(devices => devices.kind === 'videoinput')).then(cameras => { let constraints = { audio: false, video: true }; if (cameras[deviceId]) { constraints['video'] = { deviceId: { exact: cameras[deviceId].deviceId } }; } // console.log(cameras) return window.navigator.mediaDevices.getUserMedia(constraints); }).then(stream => { const video = document.createElement('video'); video.setAttribute('autoplay', ''); video.setAttribute('muted', ''); video.setAttribute('playsinline', ''); // video.src = window.URL.createObjectURL(stream) video.srcObject = stream; return new Promise((resolve, reject) => { video.addEventListener('loadedmetadata', () => { video.play().then(() => resolve({ video: video })); }); }); }).catch(console.log.bind(console)); } },{}],29:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; //const transforms = require('./glsl-transforms.js') var Output = function ({ regl, precision, label = "", width, height }) { this.regl = regl; this.precision = precision; this.label = label; this.positionBuffer = this.regl.buffer([[-2, 0], [0, -2], [2, 2]]); this.draw = () => {}; this.init(); this.pingPongIndex = 0; // for each output, create two fbos for pingponging this.fbos = Array(2).fill().map(() => this.regl.framebuffer({ color: this.regl.texture({ mag: 'nearest', width: width, height: height, format: 'rgba' }), depthStencil: false })); // array containing render passes // this.passes = [] }; Output.prototype.resize = function (width, height) { this.fbos.forEach(fbo => { fbo.resize(width, height); }); // console.log(this) }; Output.prototype.getCurrent = function () { return this.fbos[this.pingPongIndex]; }; Output.prototype.getTexture = function () { var index = this.pingPongIndex ? 0 : 1; return this.fbos[index]; }; Output.prototype.init = function () { // console.log('clearing') this.transformIndex = 0; this.fragHeader = ` precision ${this.precision} float; uniform float time; varying vec2 uv; `; this.fragBody = ``; this.vert = ` precision ${this.precision} float; attribute vec2 position; varying vec2 uv; void main () { uv = position; gl_Position = vec4(2.0 * position - 1.0, 0, 1); }`; this.attributes = { position: this.positionBuffer }; this.uniforms = { time: this.regl.prop('time'), resolution: this.regl.prop('resolution') }; this.frag = ` ${this.fragHeader} void main () { vec4 c = vec4(0, 0, 0, 0); vec2 st = uv; ${this.fragBody} gl_FragColor = c; } `; return this; }; Output.prototype.render = function (passes) { let pass = passes[0]; //console.log('pass', pass, this.pingPongIndex) var self = this; var uniforms = Object.assign(pass.uniforms, { prevBuffer: () => { //var index = this.pingPongIndex ? 0 : 1 // var index = self.pingPong[(passIndex+1)%2] // console.log('ping pong', self.pingPongIndex) return self.fbos[self.pingPongIndex]; } }); self.draw = self.regl({ frag: pass.frag, vert: self.vert, attributes: self.attributes, uniforms: uniforms, count: 3, framebuffer: () => { self.pingPongIndex = self.pingPongIndex ? 0 : 1; return self.fbos[self.pingPongIndex]; } }); }; Output.prototype.tick = function (props) { // console.log(props) this.draw(props); }; var _default = Output; exports.default = _default; },{}]},{},[19])(19) });