(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 1) er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Unhandled "error" event. (' + er + ')'); err.context = er; throw err; } return false; } handler = events[type]; if (!handler) return false; var isFn = typeof handler === 'function'; len = arguments.length; switch (len) { // fast cases case 1: emitNone(handler, isFn, this); break; case 2: emitOne(handler, isFn, this, arguments[1]); break; case 3: emitTwo(handler, isFn, this, arguments[1], arguments[2]); break; case 4: emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); break; // slower default: args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; emitMany(handler, isFn, this, args); } return true; }; function _addListener(target, type, listener, prepend) { var m; var events; var existing; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = target._events; if (!events) { events = target._events = objectCreate(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) { 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) { // 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]; } else { // If we've already got an array, just append. if (prepend) { existing.unshift(listener); } else { existing.push(listener); } } // Check for listener leak if (!existing.warned) { m = $getMaxListeners(target); if (m && m > 0 && existing.length > m) { existing.warned = true; 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; if (typeof console === 'object' && console.warn) { console.warn('%s: %s', w.name, w.message); } } } } 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; switch (arguments.length) { case 0: return this.listener.call(this.target); case 1: return this.listener.call(this.target, arguments[0]); case 2: return this.listener.call(this.target, arguments[0], arguments[1]); case 3: return this.listener.call(this.target, arguments[0], arguments[1], arguments[2]); default: var args = new Array(arguments.length); for (var i = 0; i < args.length; ++i) args[i] = arguments[i]; this.listener.apply(this.target, args); } } } function _onceWrap(target, type, listener) { var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; var wrapped = bind.call(onceWrapper, state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; } EventEmitter.prototype.once = function once(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); this.on(type, _onceWrap(this, type, listener)); return this; }; EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); 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; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = this._events; if (!events) return this; list = events[type]; if (!list) return this; if (list === listener || list.listener === listener) { if (--this._eventsCount === 0) this._events = objectCreate(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) this.emit('removeListener', type, originalListener || listener); } return this; }; EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { var listeners, events, i; events = this._events; if (!events) return this; // not listening for removeListener, no need to emit if (!events.removeListener) { if (arguments.length === 0) { this._events = objectCreate(null); this._eventsCount = 0; } else if (events[type]) { if (--this._eventsCount === 0) this._events = objectCreate(null); else delete events[type]; } return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { var keys = objectKeys(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 = objectCreate(null); this._eventsCount = 0; return this; } listeners = events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else if (listeners) { // 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) return []; var evlistener = events[type]; if (!evlistener) 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) { var evlistener = events[type]; if (typeof evlistener === 'function') { return 1; } else if (evlistener) { return evlistener.length; } } return 0; } EventEmitter.prototype.eventNames = function eventNames() { return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; }; // About 1.5x faster than the two-arg version of Array#splice(). function spliceOne(list, index) { for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) list[i] = list[k]; list.pop(); } function arrayClone(arr, n) { var copy = new Array(n); for (var i = 0; i < n; ++i) copy[i] = arr[i]; return copy; } 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 objectCreatePolyfill(proto) { var F = function() {}; F.prototype = proto; return new F; } function objectKeysPolyfill(obj) { var keys = []; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } return k; } function functionBindPolyfill(context) { var fn = this; return function () { return fn.apply(context, arguments); }; } },{}],2:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it // don't break things. But we need to wrap it in a try catch in case it is // wrapped in strict mode code which doesn't define any globals. It's inside a // function because try/catches deoptimize in certain engines. var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } } ()) function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 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; }; },{}],3:[function(require,module,exports){ const Output = require('./src/output.js') const loop = require('raf-loop') const Source = require('./src/hydra-source.js') const Mouse = require('./src/lib/mouse.js')() const Audio = require('./src/lib/audio.js') const VidRecorder = require('./src/lib/video-recorder.js') const ArrayUtils = require('./src/lib/array-utils.js') const Sandbox = require('./src/eval-sandbox.js') const Generator = require('./src/generator-factory.js') // 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.init() this.pb = pb this.width = width this.height = height this.renderAll = false this.detectAudio = detectAudio this._initCanvas(canvas) // 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 hush: this.hush.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 VidRecorder(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) loop(this.tick.bind(this)).start() // final argument is properties that the user can set, all others are treated as read-only this.sandbox = new Sandbox(this.synth, makeGlobal, ['speed', 'update', '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(1, 1, 1, 0).out(output) }) } 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 this.height = height 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({ numBins: 4, // 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 = require('regl')({ // 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({ 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 Source({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 Generator({ 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) { this.sandbox.tick() if(this.detectAudio === true) this.synth.a.tick() // let updateInterval = 1000/this.synth.fps // ms if(this.synth.update) { try { this.synth.update(dt) } catch (e) { console.log(error) } } 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) // 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) for (let i = 0; i < this.o.length; i++) { this.o[i].tick({ time: this.synth.time, 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] }) } this.timeSinceLastUpdate = 0 } if(this.saveFrame === true) { this.canvasToImage() this.saveFrame = false } // this.regl.poll() } } module.exports = HydraRenderer },{"./src/eval-sandbox.js":11,"./src/generator-factory.js":12,"./src/hydra-source.js":17,"./src/lib/array-utils.js":18,"./src/lib/audio.js":19,"./src/lib/mouse.js":22,"./src/lib/video-recorder.js":25,"./src/output.js":27,"raf-loop":7,"regl":9}],4:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, 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) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } },{}],5:[function(require,module,exports){ !function(t,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.Meyda=r():t.Meyda=r()}(this,function(){return function(t){function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var e={};return r.m=t,r.c=e,r.i=function(t){return t},r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:n})},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},r.p="",r(r.s=23)}([function(t,r,e){"use strict";function n(t){if(Array.isArray(t)){for(var r=0,e=Array(t.length);r1;)t/=2;return 1===t}function i(t,r){for(var e=[],n=0;n3&&void 0!==arguments[3]?arguments[3]:5,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:2,a=!(arguments.length>5&&void 0!==arguments[5])||arguments[5],u=arguments.length>6&&void 0!==arguments[6]?arguments[6]:440,c=Math.floor(e/2)+1,f=new Array(e).fill(0).map(function(n,o){return t*p(r*o/e,u)});f[0]=f[1]-1.5*t;var l=f.slice(1).map(function(t,r){return Math.max(t-f[r])},1).concat([1]),s=Math.round(t/2),y=new Array(t).fill(0).map(function(r,e){return f.map(function(r){return(10*t+s+r-e)%t-s})}),h=y.map(function(t,r){return t.map(function(t,e){return Math.exp(-.5*Math.pow(2*y[r][e]/l[e],2))})});if(h=m(h),i){var b=f.map(function(r){return Math.exp(-.5*Math.pow((r/t-o)/i,2))});h=h.map(function(t){return t.map(function(t,r){return t*b[r]})})}return a&&(h=[].concat(n(h.slice(3)),n(h.slice(0,3)))),h.map(function(t){return t.slice(0,c)})}function h(t,r,e){if(t.lengtha;)i[u++]=c,a=u*t.barkScale[o.length-1]/24;i[24]=o.length-1;for(var f=0;f<24;f++){for(var l=0,s=i[f];s * @license MIT */ function n(t,r){if(t===r)return 0;for(var e=t.length,n=r.length,o=0,i=Math.min(e,n);o=0;u--)if(c[u]!==f[u])return!1;for(u=c.length-1;u>=0;u--)if(a=c[u],!m(t[a],r[a],e,n))return!1;return!0}function b(t,r,e){m(t,r,!0)&&s(t,r,e,"notDeepStrictEqual",b)}function g(t,r){if(!t||!r)return!1;if("[object RegExp]"==Object.prototype.toString.call(r))return r.test(t);try{if(t instanceof r)return!0}catch(t){}return!Error.isPrototypeOf(r)&&!0===r.call({},t)}function S(t){var r;try{t()}catch(t){r=t}return r}function d(t,r,e,n){var o;if("function"!=typeof r)throw new TypeError('"block" argument must be a function');"string"==typeof e&&(n=e,e=null),o=S(r),n=(e&&e.name?" ("+e.name+").":".")+(n?" "+n:"."),t&&!o&&s(o,e,"Missing expected exception"+n);var i="string"==typeof n,a=!t&&v.isError(o),u=!t&&o&&!e;if((a&&i&&g(o,e)||u)&&s(o,e,"Got unwanted exception"+n),t&&o&&e&&!g(o,e)||!t&&o)throw o}var v=e(33),w=Object.prototype.hasOwnProperty,x=Array.prototype.slice,E=function(){return"foo"===function(){}.name}(),_=t.exports=p,M=/\s*function\s+([^\(\s]*)\s*/;_.AssertionError=function(t){this.name="AssertionError",this.actual=t.actual,this.expected=t.expected,this.operator=t.operator,t.message?(this.message=t.message,this.generatedMessage=!1):(this.message=l(this),this.generatedMessage=!0);var r=t.stackStartFunction||s;if(Error.captureStackTrace)Error.captureStackTrace(this,r);else{var e=new Error;if(e.stack){var n=e.stack,o=u(r),i=n.indexOf("\n"+o);if(i>=0){var a=n.indexOf("\n",i+1);n=n.substring(a+1)}this.stack=n}}},v.inherits(_.AssertionError,Error),_.fail=s,_.ok=p,_.equal=function(t,r,e){t!=r&&s(t,r,e,"==",_.equal)},_.notEqual=function(t,r,e){t==r&&s(t,r,e,"!=",_.notEqual)},_.deepEqual=function(t,r,e){m(t,r,!1)||s(t,r,e,"deepEqual",_.deepEqual)},_.deepStrictEqual=function(t,r,e){m(t,r,!0)||s(t,r,e,"deepStrictEqual",_.deepStrictEqual)},_.notDeepEqual=function(t,r,e){m(t,r,!1)&&s(t,r,e,"notDeepEqual",_.notDeepEqual)},_.notDeepStrictEqual=b,_.strictEqual=function(t,r,e){t!==r&&s(t,r,e,"===",_.strictEqual)},_.notStrictEqual=function(t,r,e){t===r&&s(t,r,e,"!==",_.notStrictEqual)},_.throws=function(t,r,e){d(!0,t,r,e)},_.doesNotThrow=function(t,r,e){d(!1,t,r,e)},_.ifError=function(t){if(t)throw t};var A=Object.keys||function(t){var r=[];for(var e in t)w.call(t,e)&&r.push(e);return r}}).call(r,e(5))},function(t,r,e){"use strict";function n(t){if(Array.isArray(t)){for(var r=0,e=Array(t.length);rr&&(r=t.specific[i]);return Math.pow((t.total-r)/t.total,2)}},function(t,r,e){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};r.a=function(t){if("object"!==n(t.signal))throw new TypeError;for(var r=0,e=0;ei&&a>=0;)e-=t[a],--a;return(a+1)*r}},function(t,r,e){"use strict";var n=e(1),o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};r.a=function(t){if("object"!==o(t.ampSpectrum))throw new TypeError;var r=e.i(n.a)(1,t.ampSpectrum),i=e.i(n.a)(2,t.ampSpectrum),a=e.i(n.a)(3,t.ampSpectrum);return(2*Math.pow(r,3)-3*r*i+a)/Math.pow(Math.sqrt(i-Math.pow(r,2)),3)}},function(t,r,e){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};r.a=function(t){if("object"!==n(t.ampSpectrum))throw new TypeError;for(var r=0,e=0,o=new Float32Array(t.ampSpectrum.length),i=0,a=0,u=0;u=0&&arguments[0].signal[r+1]<0||arguments[0].signal[r]<0&&arguments[0].signal[r+1]>=0)&&t++;return t}},function(t,r,e){t.exports=e(6).default},function(t,r,e){"use strict";function n(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")}e.d(r,"a",function(){return u});var o=e(0),i=e(4),a=function(){function t(t,r){for(var e=0;e0;i--)r[t-i]=r[i-1];return r}function o(t){for(var r=Math.PI/(t-1),e=new Float32Array(t),n=0;n1)for(var e=1;e=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),h(e)?n.showHidden=e:e&&r._extend(n,e),w(n.showHidden)&&(n.showHidden=!1),w(n.depth)&&(n.depth=2),w(n.colors)&&(n.colors=!1),w(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=i),c(n,t,n.depth)}function i(t,r){var e=o.styles[r];return e?"["+o.colors[e][0]+"m"+t+"["+o.colors[e][1]+"m":t}function a(t,r){return t}function u(t){var r={};return t.forEach(function(t,e){r[t]=!0}),r}function c(t,e,n){if(t.customInspect&&e&&A(e.inspect)&&e.inspect!==r.inspect&&(!e.constructor||e.constructor.prototype!==e)){var o=e.inspect(n,t);return d(o)||(o=c(t,o,n)),o}var i=f(t,e);if(i)return i;var a=Object.keys(e),h=u(a);if(t.showHidden&&(a=Object.getOwnPropertyNames(e)),M(e)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return l(e);if(0===a.length){if(A(e)){var b=e.name?": "+e.name:"";return t.stylize("[Function"+b+"]","special")}if(x(e))return t.stylize(RegExp.prototype.toString.call(e),"regexp");if(_(e))return t.stylize(Date.prototype.toString.call(e),"date");if(M(e))return l(e)}var g="",S=!1,v=["{","}"];if(y(e)&&(S=!0,v=["[","]"]),A(e)){g=" [Function"+(e.name?": "+e.name:"")+"]"}if(x(e)&&(g=" "+RegExp.prototype.toString.call(e)),_(e)&&(g=" "+Date.prototype.toUTCString.call(e)),M(e)&&(g=" "+l(e)),0===a.length&&(!S||0==e.length))return v[0]+g+v[1];if(n<0)return x(e)?t.stylize(RegExp.prototype.toString.call(e),"regexp"):t.stylize("[Object]","special");t.seen.push(e);var w;return w=S?s(t,e,n,h,a):a.map(function(r){return p(t,e,n,h,r,S)}),t.seen.pop(),m(w,g,v)}function f(t,r){if(w(r))return t.stylize("undefined","undefined");if(d(r)){var e="'"+JSON.stringify(r).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return t.stylize(e,"string")}return S(r)?t.stylize(""+r,"number"):h(r)?t.stylize(""+r,"boolean"):b(r)?t.stylize("null","null"):void 0}function l(t){return"["+Error.prototype.toString.call(t)+"]"}function s(t,r,e,n,o){for(var i=[],a=0,u=r.length;a-1&&(u=i?u.split("\n").map(function(t){return" "+t}).join("\n").substr(2):"\n"+u.split("\n").map(function(t){return" "+t}).join("\n"))):u=t.stylize("[Circular]","special")),w(a)){if(i&&o.match(/^\d+$/))return u;a=JSON.stringify(""+o),a.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=t.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=t.stylize(a,"string"))}return a+": "+u}function m(t,r,e){var n=0;return t.reduce(function(t,r){return n++,r.indexOf("\n")>=0&&n++,t+r.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60?e[0]+(""===r?"":r+"\n ")+" "+t.join(",\n ")+" "+e[1]:e[0]+r+" "+t.join(", ")+" "+e[1]}function y(t){return Array.isArray(t)}function h(t){return"boolean"==typeof t}function b(t){return null===t}function g(t){return null==t}function S(t){return"number"==typeof t}function d(t){return"string"==typeof t}function v(t){return"symbol"==typeof t}function w(t){return void 0===t}function x(t){return E(t)&&"[object RegExp]"===T(t)}function E(t){return"object"==typeof t&&null!==t}function _(t){return E(t)&&"[object Date]"===T(t)}function M(t){return E(t)&&("[object Error]"===T(t)||t instanceof Error)}function A(t){return"function"==typeof t}function j(t){return null===t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t||"symbol"==typeof t||void 0===t}function T(t){return Object.prototype.toString.call(t)}function F(t){return t<10?"0"+t.toString(10):t.toString(10)}function k(){var t=new Date,r=[F(t.getHours()),F(t.getMinutes()),F(t.getSeconds())].join(":");return[t.getDate(),R[t.getMonth()],r].join(" ")}function z(t,r){return Object.prototype.hasOwnProperty.call(t,r)}var O=/%[sdj%]/g;r.format=function(t){if(!d(t)){for(var r=[],e=0;e=i)return t;switch(t){case"%s":return String(n[e++]);case"%d":return Number(n[e++]);case"%j":try{return JSON.stringify(n[e++])}catch(t){return"[Circular]"}default:return t}}),u=n[e];e>>=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) } } module.exports = EvalSandbox },{"./lib/array-utils.js":18,"./lib/sandbox.js":23}],12:[function(require,module,exports){ const GlslSource = require('./glsl-source.js') class GeneratorFactory { constructor ({ defaultUniforms, defaultOutput, extendTransforms = [], changeListener = (() => {}) } = {} ) { this.defaultOutput = defaultOutput this.defaultUniforms = defaultUniforms this.changeListener = changeListener this.extendTransforms = extendTransforms this.generators = {} this.init() } init () { 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 { } })() let functions = require('./glsl/glsl-functions.js')() // 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) { 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: this }) 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}) return this } } return undefined } setFunction(obj) { var processedGlsl = processGlsl(obj) if(processedGlsl) this._addMethod(obj.name, processedGlsl) } } const typeLookup = { 'src': { returnType: 'vec4', args: ['vec2 _st'] }, 'coord': { returnType: 'vec2', args: ['vec2 _st'] }, 'color': { returnType: 'vec4', args: ['vec4 _c0'] }, 'combine': { returnType: 'vec4', args: ['vec4 _c0', 'vec4 _c1'] }, 'combineCoord': { returnType: 'vec2', args: ['vec2 _st', 'vec4 _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 baseArgs = t.args.map((arg) => arg).join(", ") // @todo: make sure this works for all input types, add validation let customArgs = obj.inputs.map((input) => `${input.type} ${input.name}`).join(', ') let args = `${baseArgs}${customArgs.length > 0 ? ', '+ customArgs: ''}` // console.log('args are ', args) let glslFunction = ` ${t.returnType} ${obj.name}(${args}) { ${obj.glsl} } ` // add extra input to beginning for backward combatibility @todo update compiler so this is no longer necessary if(obj.type === 'combine' || obj.type === 'combineCoord') obj.inputs.unshift({ name: 'color', type: 'vec4' }) return Object.assign({}, obj, { glsl: glslFunction}) } else { console.warn(`type ${obj.type} not recognized`, obj) } } module.exports = GeneratorFactory },{"./glsl-source.js":13,"./glsl/glsl-functions.js":15}],13:[function(require,module,exports){ const generateGlsl = require('./glsl-utils.js').generateGlsl const formatArguments = require('./glsl-utils.js').formatArguments // const glslTransforms = require('./glsl/composable-glsl-functions.js') const utilityGlsl = require('./glsl/utility-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 var glsl = this.glsl(output) this.synth.currentFunctions = [] // output.renderPasses(glsl) if(output) try{ output.render(glsl) } catch (error) { console.log('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 = generateGlsl(transforms) 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(utilityGlsl).map((transform) => { // console.log(transform.glsl) return ` ${transform.glsl} ` }).join('')} ${shaderInfo.glslFunctions.map((transform) => { return ` ${transform.transform.glsl} ` }).join('')} void main () { vec4 c = vec4(1, 0, 0, 1); vec2 st = gl_FragCoord.xy/resolution.xy; gl_FragColor = ${shaderInfo.fragColor}; } ` return { frag: frag, uniforms: Object.assign({}, this.defaultUniforms, uniforms) } } module.exports = GlslSource },{"./glsl-utils.js":14,"./glsl/utility-functions.js":16}],14:[function(require,module,exports){ // converts a tree of javascript functions to a shader // Add extra functionality to Array.prototype for generating sequences in time const arrayUtils = require('./lib/array-utils.js') // [WIP] how to treat different dimensions (?) const DEFAULT_CONVERSIONS = { float: { 'vec4': {name: 'sum', args: [[1, 1, 1, 1]]}, 'vec2': {name: 'sum', args: [[1, 1]]} } } module.exports = { generateGlsl: function (transforms) { var shaderParams = { uniforms: [], // list of uniforms used in shader glslFunctions: [], // list of functions used in shader fragColor: '' } var gen = generateGlsl(transforms, shaderParams)('st') 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 }, formatArguments: formatArguments } // recursive function for generating shader string from object containing functions and user arguments. Order of functions in string depends on type of function // to do: improve variable names function generateGlsl (transforms, shaderParams) { // transform function that outputs a shader string corresponding to gl_FragColor var fragColor = () => '' // var uniforms = [] // var glslFunctions = [] transforms.forEach((transform) => { var inputs = formatArguments(transform, shaderParams.uniforms.length) // console.log('inputs', inputs, transform) inputs.forEach((input) => { if(input.isUniform) shaderParams.uniforms.push(input) }) // add new glsl function to running list of functions if(!contains(transform, shaderParams.glslFunctions)) shaderParams.glslFunctions.push(transform) // current function for generating frag color shader code var f0 = fragColor if (transform.transform.type === 'src') { fragColor = (uv) => `${shaderString(uv, transform.name, inputs, shaderParams)}` } else if (transform.transform.type === 'coord') { fragColor = (uv) => `${f0(`${shaderString(uv, transform.name, inputs, shaderParams)}`)}` } else if (transform.transform.type === 'color') { fragColor = (uv) => `${shaderString(`${f0(uv)}`, transform.name, inputs, shaderParams)}` } else if (transform.transform.type === 'combine') { // combining two generated shader strings (i.e. for blend, mult, add funtions) var f1 = inputs[0].value && inputs[0].value.transforms ? (uv) => `${generateGlsl(inputs[0].value.transforms, shaderParams)(uv)}` : (inputs[0].isUniform ? () => inputs[0].name : () => inputs[0].value) fragColor = (uv) => `${shaderString(`${f0(uv)}, ${f1(uv)}`, transform.name, inputs.slice(1), shaderParams)}` } else if (transform.transform.type === 'combineCoord') { // combining two generated shader strings (i.e. for modulate functions) var f1 = inputs[0].value && inputs[0].value.transforms ? (uv) => `${generateGlsl(inputs[0].value.transforms, shaderParams)(uv)}` : (inputs[0].isUniform ? () => inputs[0].name : () => inputs[0].value) fragColor = (uv) => `${f0(`${shaderString(`${uv}, ${f1(uv)}`, transform.name, inputs.slice(1), shaderParams)}`)}` } }) // console.log(fragColor) // break; return fragColor } // assembles a shader string containing the arguments and the function name, i.e. 'osc(uv, frequency)' function shaderString (uv, method, inputs, shaderParams) { const str = inputs.map((input) => { if (input.isUniform) { return input.name } else if (input.value && input.value.transforms) { // this by definition needs to be a generator, hence we start with 'st' as the initial value for generating the glsl fragment return `${generateGlsl(input.value.transforms, shaderParams)('st')}` } 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 } 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) { // console.log('processing args', transform, startIndex) const defaultArgs = transform.transform.inputs const userArgs = transform.userArgs 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] // 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 { return userArgs[index](props) } catch (e) { console.log('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") typedArg.value = (context, props, batchId) => arrayUtils.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":18}],15:[function(require,module,exports){ /* 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', 'combineCoords'. 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: ['vec2 _st'] }, 'coord': { returnType: 'vec2', args: ['vec2 _st'] }, 'color': { returnType: 'vec4', args: ['vec4 _c0'] }, 'combine': { returnType: 'vec4', args: ['vec4 _c0', 'vec4 _c1'] }, 'combineCoord': { returnType: 'vec2', args: ['vec2 _st', 'vec4 _c0'] } } */ module.exports = () => [ { 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(c2.r + r); c2.g = fract(c2.g + g); c2.b = fract(c2.b + b); c2.a = fract(c2.a + 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), _c0.a+_c1.a);` }, { 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);` }, { 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);` } ] },{}],16:[function(require,module,exports){ // functions that are only used within other functions module.exports = { _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); }` } } },{}],17:[function(require,module,exports){ const Webcam = require('./lib/webcam.js') const Screen = require('./lib/screenmedia.js') 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) { if (opts.src) { this.src = opts.src this.tex = this.regl.texture(this.src) } if (opts.dynamic) this.dynamic = opts.dynamic } initCam (index) { const self = this Webcam(index) .then(response => { self.src = response.video self.dynamic = true self.tex = self.regl.texture(self.src) }) .catch(err => console.log('could not get camera', err)) } initVideo (url = '') { // 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(this.src) this.dynamic = true }) vid.src = url } initImage (url = '') { const img = document.createElement('img') img.crossOrigin = 'anonymous' img.src = url img.onload = () => { this.src = img this.dynamic = false this.tex = this.regl.texture(this.src) } } initStream (streamName) { // 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(self.src) } }) } } initScreen () { const self = this Screen() .then(function (response) { self.src = response.video self.tex = self.regl.texture(self.src) self.dynamic = true // console.log("received screen input") }) .catch(err => console.log('could not get screen', err)) } 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 !== null && 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 } } module.exports = HydraSource },{"./lib/screenmedia.js":24,"./lib/webcam.js":26}],18:[function(require,module,exports){ // 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 easing = require('./easing-functions.js') 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; } module.exports = { 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 (easing[ease]){ this._smooth = 1 this._ease = easing[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 : easing['linear'] let _index = index - (smooth / 2) let currValue = arr[Math.floor(_index % (arr.length))] let nextValue = arr[Math.floor((_index + 1) % (arr.length))] let t = Math.min((_index%1)/smooth,1) return ease(t) * (nextValue - currValue) + currValue } else { return arr[Math.floor(index % (arr.length))] } } } },{"./easing-functions.js":20}],19:[function(require,module,exports){ const Meyda = require('meyda') class Audio { constructor ({ numBins = 4, cutoff = 2, smooth = 0.4, max = 15, scale = 10, isDrawing = false }) { 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' document.body.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 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.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()*/ } } module.exports = Audio },{"meyda":5}],20:[function(require,module,exports){ // from https://gist.github.com/gre/1650294 module.exports = { // 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 } } },{}],21:[function(require,module,exports){ // https://github.com/mikolalysenko/mouse-event 'use strict' 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< { 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) { eval(initial) // optional params var localEval = function (code) { eval(code) } // API/data for end-user return { eval: localEval } } } },{}],24:[function(require,module,exports){ module.exports = function (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)) }) } },{}],25:[function(require,module,exports){ 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); } } } module.exports = VideoRecorder },{}],26:[function(require,module,exports){ //const enumerateDevices = require('enumerate-devices') module.exports = function (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.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)) } },{}],27:[function(require,module,exports){ //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) } module.exports = Output },{}]},{},[3])(3) });