(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("butterchurn", [], factory); else if(typeof exports === 'object') exports["butterchurn"] = factory(); else root["butterchurn"] = factory(); })(window, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./node_modules/@assemblyscript/loader/index.js": /*!******************************************************!*\ !*** ./node_modules/@assemblyscript/loader/index.js ***! \******************************************************/ /*! exports provided: instantiate, instantiateSync, instantiateStreaming, demangle, default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "instantiate", function() { return instantiate; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "instantiateSync", function() { return instantiateSync; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "instantiateStreaming", function() { return instantiateStreaming; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "demangle", function() { return demangle; }); // Runtime header offsets const ID_OFFSET = -8; const SIZE_OFFSET = -4; // Runtime ids const ARRAYBUFFER_ID = 0; const STRING_ID = 1; // const ARRAYBUFFERVIEW_ID = 2; // Runtime type information const ARRAYBUFFERVIEW = 1 << 0; const ARRAY = 1 << 1; const STATICARRAY = 1 << 2; // const SET = 1 << 3; // const MAP = 1 << 4; const VAL_ALIGN_OFFSET = 6; // const VAL_ALIGN = 1 << VAL_ALIGN_OFFSET; const VAL_SIGNED = 1 << 11; const VAL_FLOAT = 1 << 12; // const VAL_NULLABLE = 1 << 13; const VAL_MANAGED = 1 << 14; // const KEY_ALIGN_OFFSET = 15; // const KEY_ALIGN = 1 << KEY_ALIGN_OFFSET; // const KEY_SIGNED = 1 << 20; // const KEY_FLOAT = 1 << 21; // const KEY_NULLABLE = 1 << 22; // const KEY_MANAGED = 1 << 23; // Array(BufferView) layout const ARRAYBUFFERVIEW_BUFFER_OFFSET = 0; const ARRAYBUFFERVIEW_DATASTART_OFFSET = 4; const ARRAYBUFFERVIEW_DATALENGTH_OFFSET = 8; const ARRAYBUFFERVIEW_SIZE = 12; const ARRAY_LENGTH_OFFSET = 12; const ARRAY_SIZE = 16; const BIGINT = typeof BigUint64Array !== "undefined"; const THIS = Symbol(); const STRING_DECODE_THRESHOLD = 32; const decoder = new TextDecoder("utf-16le"); /** Gets a string from an U32 and an U16 view on a memory. */ function getStringImpl(buffer, ptr) { const len = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2] >>> 1; const arr = new Uint16Array(buffer, ptr, len); if (len <= STRING_DECODE_THRESHOLD) { return String.fromCharCode.apply(String, arr); } return decoder.decode(arr); } /** Prepares the base module prior to instantiation. */ function preInstantiate(imports) { const extendedExports = {}; function getString(memory, ptr) { if (!memory) return ""; return getStringImpl(memory.buffer, ptr); } // add common imports used by stdlib for convenience const env = (imports.env = imports.env || {}); env.abort = env.abort || function abort(msg, file, line, colm) { const memory = extendedExports.memory || env.memory; // prefer exported, otherwise try imported throw Error(`abort: ${getString(memory, msg)} at ${getString(memory, file)}:${line}:${colm}`); }; env.trace = env.trace || function trace(msg, n, ...args) { const memory = extendedExports.memory || env.memory; console.log(`trace: ${getString(memory, msg)}${n ? " " : ""}${args.slice(0, n).join(", ")}`); }; env.seed = env.seed || Date.now; imports.Math = imports.Math || Math; imports.Date = imports.Date || Date; return extendedExports; } /** Prepares the final module once instantiation is complete. */ function postInstantiate(extendedExports, instance) { const exports = instance.exports; const memory = exports.memory; const table = exports.table; const __new = exports["__new"]; const __retain = exports["__retain"]; const __rtti_base = exports["__rtti_base"] || ~0; // oob if not present /** Gets the runtime type info for the given id. */ function getInfo(id) { const U32 = new Uint32Array(memory.buffer); const count = U32[__rtti_base >>> 2]; if ((id >>>= 0) >= count) throw Error(`invalid id: ${id}`); return U32[(__rtti_base + 4 >>> 2) + id * 2]; } /** Gets and validate runtime type info for the given id for array like objects */ function getArrayInfo(id) { const info = getInfo(id); if (!(info & (ARRAYBUFFERVIEW | ARRAY | STATICARRAY))) throw Error(`not an array: ${id}, flags=${info}`); return info; } /** Gets the runtime base id for the given id. */ function getBase(id) { const U32 = new Uint32Array(memory.buffer); const count = U32[__rtti_base >>> 2]; if ((id >>>= 0) >= count) throw Error(`invalid id: ${id}`); return U32[(__rtti_base + 4 >>> 2) + id * 2 + 1]; } /** Gets the runtime alignment of a collection's values. */ function getValueAlign(info) { return 31 - Math.clz32((info >>> VAL_ALIGN_OFFSET) & 31); // -1 if none } /** Gets the runtime alignment of a collection's keys. */ // function getKeyAlign(info) { // return 31 - Math.clz32((info >>> KEY_ALIGN_OFFSET) & 31); // -1 if none // } /** Allocates a new string in the module's memory and returns its retained pointer. */ function __newString(str) { if (str == null) return 0; const length = str.length; const ptr = __new(length << 1, STRING_ID); const U16 = new Uint16Array(memory.buffer); for (var i = 0, p = ptr >>> 1; i < length; ++i) U16[p + i] = str.charCodeAt(i); return ptr; } extendedExports.__newString = __newString; /** Reads a string from the module's memory by its pointer. */ function __getString(ptr) { if (!ptr) return null; const buffer = memory.buffer; const id = new Uint32Array(buffer)[ptr + ID_OFFSET >>> 2]; if (id !== STRING_ID) throw Error(`not a string: ${ptr}`); return getStringImpl(buffer, ptr); } extendedExports.__getString = __getString; /** Gets the view matching the specified alignment, signedness and floatness. */ function getView(alignLog2, signed, float) { const buffer = memory.buffer; if (float) { switch (alignLog2) { case 2: return new Float32Array(buffer); case 3: return new Float64Array(buffer); } } else { switch (alignLog2) { case 0: return new (signed ? Int8Array : Uint8Array)(buffer); case 1: return new (signed ? Int16Array : Uint16Array)(buffer); case 2: return new (signed ? Int32Array : Uint32Array)(buffer); case 3: return new (signed ? BigInt64Array : BigUint64Array)(buffer); } } throw Error(`unsupported align: ${alignLog2}`); } /** Allocates a new array in the module's memory and returns its retained pointer. */ function __newArray(id, values) { const info = getArrayInfo(id); const align = getValueAlign(info); const length = values.length; const buf = __new(length << align, info & STATICARRAY ? id : ARRAYBUFFER_ID); let result; if (info & STATICARRAY) { result = buf; } else { const arr = __new(info & ARRAY ? ARRAY_SIZE : ARRAYBUFFERVIEW_SIZE, id); const U32 = new Uint32Array(memory.buffer); U32[arr + ARRAYBUFFERVIEW_BUFFER_OFFSET >>> 2] = __retain(buf); U32[arr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2] = buf; U32[arr + ARRAYBUFFERVIEW_DATALENGTH_OFFSET >>> 2] = length << align; if (info & ARRAY) U32[arr + ARRAY_LENGTH_OFFSET >>> 2] = length; result = arr; } const view = getView(align, info & VAL_SIGNED, info & VAL_FLOAT); if (info & VAL_MANAGED) { for (let i = 0; i < length; ++i) view[(buf >>> align) + i] = __retain(values[i]); } else { view.set(values, buf >>> align); } return result; } extendedExports.__newArray = __newArray; /** Gets a live view on an array's values in the module's memory. Infers the array type from RTTI. */ function __getArrayView(arr) { const U32 = new Uint32Array(memory.buffer); const id = U32[arr + ID_OFFSET >>> 2]; const info = getArrayInfo(id); const align = getValueAlign(info); let buf = info & STATICARRAY ? arr : U32[arr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2]; const length = info & ARRAY ? U32[arr + ARRAY_LENGTH_OFFSET >>> 2] : U32[buf + SIZE_OFFSET >>> 2] >>> align; return getView(align, info & VAL_SIGNED, info & VAL_FLOAT).subarray(buf >>>= align, buf + length); } extendedExports.__getArrayView = __getArrayView; /** Copies an array's values from the module's memory. Infers the array type from RTTI. */ function __getArray(arr) { const input = __getArrayView(arr); const len = input.length; const out = new Array(len); for (let i = 0; i < len; i++) out[i] = input[i]; return out; } extendedExports.__getArray = __getArray; /** Copies an ArrayBuffer's value from the module's memory. */ function __getArrayBuffer(ptr) { const buffer = memory.buffer; const length = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2]; return buffer.slice(ptr, ptr + length); } extendedExports.__getArrayBuffer = __getArrayBuffer; /** Copies a typed array's values from the module's memory. */ function getTypedArray(Type, alignLog2, ptr) { return new Type(getTypedArrayView(Type, alignLog2, ptr)); } /** Gets a live view on a typed array's values in the module's memory. */ function getTypedArrayView(Type, alignLog2, ptr) { const buffer = memory.buffer; const U32 = new Uint32Array(buffer); const bufPtr = U32[ptr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2]; return new Type(buffer, bufPtr, U32[bufPtr + SIZE_OFFSET >>> 2] >>> alignLog2); } /** Attach a set of get TypedArray and View functions to the exports. */ function attachTypedArrayFunctions(ctor, name, align) { extendedExports[`__get${name}`] = getTypedArray.bind(null, ctor, align); extendedExports[`__get${name}View`] = getTypedArrayView.bind(null, ctor, align); } [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ].forEach(ctor => { attachTypedArrayFunctions(ctor, ctor.name, 31 - Math.clz32(ctor.BYTES_PER_ELEMENT)); }); if (BIGINT) { [BigUint64Array, BigInt64Array].forEach(ctor => { attachTypedArrayFunctions(ctor, ctor.name.slice(3), 3); }); } /** Tests whether an object is an instance of the class represented by the specified base id. */ function __instanceof(ptr, baseId) { const U32 = new Uint32Array(memory.buffer); let id = U32[ptr + ID_OFFSET >>> 2]; if (id <= U32[__rtti_base >>> 2]) { do { if (id == baseId) return true; id = getBase(id); } while (id); } return false; } extendedExports.__instanceof = __instanceof; // Pull basic exports to extendedExports so code in preInstantiate can use them extendedExports.memory = extendedExports.memory || memory; extendedExports.table = extendedExports.table || table; // Demangle exports and provide the usual utility on the prototype return demangle(exports, extendedExports); } function isResponse(src) { return typeof Response !== "undefined" && src instanceof Response; } function isModule(src) { return src instanceof WebAssembly.Module; } /** Asynchronously instantiates an AssemblyScript module from anything that can be instantiated. */ async function instantiate(source, imports = {}) { if (isResponse(source = await source)) return instantiateStreaming(source, imports); const module = isModule(source) ? source : await WebAssembly.compile(source); const extended = preInstantiate(imports); const instance = await WebAssembly.instantiate(module, imports); const exports = postInstantiate(extended, instance); return { module, instance, exports }; } /** Synchronously instantiates an AssemblyScript module from a WebAssembly.Module or binary buffer. */ function instantiateSync(source, imports = {}) { const module = isModule(source) ? source : new WebAssembly.Module(source); const extended = preInstantiate(imports); const instance = new WebAssembly.Instance(module, imports); const exports = postInstantiate(extended, instance); return { module, instance, exports }; } /** Asynchronously instantiates an AssemblyScript module from a response, i.e. as obtained by `fetch`. */ async function instantiateStreaming(source, imports = {}) { if (!WebAssembly.instantiateStreaming) { return instantiate( isResponse(source = await source) ? source.arrayBuffer() : source, imports ); } const extended = preInstantiate(imports); const result = await WebAssembly.instantiateStreaming(source, imports); const exports = postInstantiate(extended, result.instance); return { ...result, exports }; } /** Demangles an AssemblyScript module's exports to a friendly object structure. */ function demangle(exports, extendedExports = {}) { const setArgumentsLength = exports["__argumentsLength"] ? length => { exports["__argumentsLength"].value = length; } : exports["__setArgumentsLength"] || exports["__setargc"] || (() => { /* nop */ }); for (let internalName in exports) { if (!Object.prototype.hasOwnProperty.call(exports, internalName)) continue; const elem = exports[internalName]; let parts = internalName.split("."); let curr = extendedExports; while (parts.length > 1) { let part = parts.shift(); if (!Object.prototype.hasOwnProperty.call(curr, part)) curr[part] = {}; curr = curr[part]; } let name = parts[0]; let hash = name.indexOf("#"); if (hash >= 0) { const className = name.substring(0, hash); const classElem = curr[className]; if (typeof classElem === "undefined" || !classElem.prototype) { const ctor = function(...args) { return ctor.wrap(ctor.prototype.constructor(0, ...args)); }; ctor.prototype = { valueOf() { return this[THIS]; } }; ctor.wrap = function(thisValue) { return Object.create(ctor.prototype, { [THIS]: { value: thisValue, writable: false } }); }; if (classElem) Object.getOwnPropertyNames(classElem).forEach(name => Object.defineProperty(ctor, name, Object.getOwnPropertyDescriptor(classElem, name)) ); curr[className] = ctor; } name = name.substring(hash + 1); curr = curr[className].prototype; if (/^(get|set):/.test(name)) { if (!Object.prototype.hasOwnProperty.call(curr, name = name.substring(4))) { let getter = exports[internalName.replace("set:", "get:")]; let setter = exports[internalName.replace("get:", "set:")]; Object.defineProperty(curr, name, { get() { return getter(this[THIS]); }, set(value) { setter(this[THIS], value); }, enumerable: true }); } } else { if (name === 'constructor') { (curr[name] = (...args) => { setArgumentsLength(args.length); return elem(...args); }).original = elem; } else { // instance method (curr[name] = function(...args) { // ! setArgumentsLength(args.length); return elem(this[THIS], ...args); }).original = elem; } } } else { if (/^(get|set):/.test(name)) { if (!Object.prototype.hasOwnProperty.call(curr, name = name.substring(4))) { Object.defineProperty(curr, name, { get: exports[internalName.replace("set:", "get:")], set: exports[internalName.replace("get:", "set:")], enumerable: true }); } } else if (typeof elem === "function" && elem !== setArgumentsLength) { (curr[name] = (...args) => { setArgumentsLength(args.length); return elem(...args); }).original = elem; } else { curr[name] = elem; } } } return extendedExports; } /* harmony default export */ __webpack_exports__["default"] = ({ instantiate, instantiateSync, instantiateStreaming, demangle }); /***/ }), /***/ "./node_modules/@babel/runtime/helpers/defineProperty.js": /*!***************************************************************!*\ !*** ./node_modules/@babel/runtime/helpers/defineProperty.js ***! \***************************************************************/ /*! no static exports found */ /***/ (function(module, exports) { function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } module.exports = _defineProperty; /***/ }), /***/ "./node_modules/ecma-proposal-math-extensions/reference-implementation/index.js": /*!**************************************************************************************!*\ !*** ./node_modules/ecma-proposal-math-extensions/reference-implementation/index.js ***! \**************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; { const defineMath = (name, assignment) => { var configurable = typeof assignment === "function" ? true : false; var writable = typeof assignment === "function" ? true : false; var enumerable = typeof assignment === "function" ? true : false; Object.defineProperty(Math, name, { configurable: configurable, enumerable: enumerable, writable: writable, value: assignment }); }; defineMath("DEG_PER_RAD", Math.PI / 180); defineMath("RAD_PER_DEG", 180 / Math.PI); const f32A = new Float32Array(1); defineMath("scale", function scale(x, inLow, inHigh, outLow, outHigh) { if (arguments.length === 0) { return NaN; } if (Number.isNaN(x) || Number.isNaN(inLow) || Number.isNaN(inHigh) || Number.isNaN(outLow) || Number.isNaN(outHigh)) { return NaN; } if (x === Infinity || x === -Infinity) { return x; } return (x - inLow) * (outHigh - outLow) / (inHigh - inLow) + outLow; }); defineMath("fscale", function fscale(x, inLow, inHigh, outLow, outHigh) { f32A[0] = Math.scale(x, inLow, inHigh, outLow, outHigh); return f32A[0]; }); defineMath("clamp", function clamp(x, lower, upper) { return Math.min(upper, Math.max(lower, x)); }); defineMath("radians", function radians(degrees) { return degrees * Math.DEG_PER_RAD; }); defineMath("degrees", function degrees(radians) { return radians * Math.RAD_PER_DEG; }); } /***/ }), /***/ "./node_modules/eel-wasm/dist/build/parser.js": /*!****************************************************!*\ !*** ./node_modules/eel-wasm/dist/build/parser.js ***! \****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module, process) {/* parser generated by jison 0.4.18 */ /* Returns a Parser object of the following structure: Parser: { yy: {} } Parser.prototype: { yy: {}, trace: function(), symbols_: {associative list: name ==> number}, terminals_: {associative list: number ==> name}, productions_: [...], performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), table: [...], defaultActions: {...}, parseError: function(str, hash), parse: function(input), lexer: { EOF: 1, parseError: function(str, hash), setInput: function(input), input: function(), unput: function(str), more: function(), less: function(n), pastInput: function(), upcomingInput: function(), showPosition: function(), test_match: function(regex_match_array, rule_index), next: function(), lex: function(), begin: function(condition), popState: function(), _currentRules: function(), topState: function(), pushState: function(condition), options: { ranges: boolean (optional: true ==> token location info will include a .range[] member) flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) }, performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), rules: [...], conditions: {associative list: name ==> set}, } } token location info (@$, _$, etc.): { first_line: n, last_line: n, first_column: n, last_column: n, range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) } the parseError function receives a 'hash' object with these members for lexer and parser errors: { text: (matched text) token: (the produced terminal token, if any) line: (yylineno) } while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { loc: (yylloc) expected: (string describing the set of expected tokens) recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) } */ var parser = (function () { var o = function (k, v, o, l) { for (o = o || {}, l = k.length; l--; o[k[l]] = v) ; return o; }, $V0 = [1, 18], $V1 = [1, 7], $V2 = [1, 19], $V3 = [1, 20], $V4 = [1, 14], $V5 = [1, 15], $V6 = [1, 16], $V7 = [1, 33], $V8 = [1, 31], $V9 = [1, 23], $Va = [1, 22], $Vb = [1, 24], $Vc = [1, 25], $Vd = [1, 26], $Ve = [1, 27], $Vf = [1, 28], $Vg = [1, 29], $Vh = [1, 30], $Vi = [5, 8, 15, 18, 20, 28, 29, 32, 33, 34, 35, 36, 37, 38], $Vj = [5, 15, 18], $Vk = [5, 12, 15, 17, 18, 24, 25, 28, 29, 30], $Vl = [1, 57], $Vm = [5, 8, 12, 15, 17, 18, 24, 25, 28, 29, 30], $Vn = [15, 18], $Vo = [5, 8, 15, 18, 28, 29, 38], $Vp = [5, 8, 15, 18, 28, 29, 32, 33, 38], $Vq = [5, 8, 15, 18, 28, 29, 32, 33, 34, 37, 38], $Vr = [5, 8, 15, 18, 28, 29, 32, 33, 34, 35, 36, 37, 38], $Vs = [5, 8, 15, 18], $Vt = [5, 8, 15, 18, 20, 22, 28, 29, 32, 33, 34, 35, 36, 37, 38]; var parser = { trace: function trace() { }, yy: {}, symbols_: { "error": 2, "SCRIPT": 3, "expression": 4, "EOF": 5, "expressionsOptionalTrailingSemi": 6, "separator": 7, ";": 8, "expressions": 9, "EXPRESSION_BLOCK": 10, "IDENTIFIER": 11, "IDENTIFIER_TOKEN": 12, "argument": 13, "arguments": 14, ",": 15, "FUNCTION_CALL": 16, "(": 17, ")": 18, "LOGICAL_EXPRESSION": 19, "LOGICAL_OPERATOR_TOKEN": 20, "ASSIGNMENT": 21, "ASSIGNMENT_OPERATOR_TOKEN": 22, "number": 23, "DIGITS_TOKEN": 24, ".": 25, "NUMBER_LITERAL": 26, "UNARY_EXPRESSION": 27, "-": 28, "+": 29, "!": 30, "BINARY_EXPRESSION": 31, "*": 32, "/": 33, "%": 34, "&": 35, "|": 36, "^": 37, "COMPARISON_TOKEN": 38, "$accept": 0, "$end": 1 }, terminals_: { 2: "error", 5: "EOF", 8: ";", 12: "IDENTIFIER_TOKEN", 15: ",", 17: "(", 18: ")", 20: "LOGICAL_OPERATOR_TOKEN", 22: "ASSIGNMENT_OPERATOR_TOKEN", 24: "DIGITS_TOKEN", 25: ".", 28: "-", 29: "+", 30: "!", 32: "*", 33: "/", 34: "%", 35: "&", 36: "|", 37: "^", 38: "COMPARISON_TOKEN" }, productions_: [0, [3, 2], [3, 2], [3, 1], [7, 1], [7, 2], [9, 2], [9, 3], [6, 1], [6, 2], [10, 1], [11, 1], [13, 1], [13, 1], [14, 1], [14, 3], [16, 3], [16, 4], [19, 3], [21, 3], [21, 3], [23, 1], [23, 2], [23, 3], [23, 2], [23, 1], [26, 1], [27, 2], [27, 2], [27, 2], [31, 3], [31, 3], [31, 3], [31, 3], [31, 3], [31, 3], [31, 3], [31, 3], [31, 3], [4, 1], [4, 1], [4, 3], [4, 1], [4, 1], [4, 1], [4, 1], [4, 1], [4, 3]], performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { /* this == yyval */ var $0 = $$.length - 1; switch (yystate) { case 1: return { type: 'SCRIPT', body: [$$[$0 - 1]], loc: this._$ }; break; case 2: return { type: 'SCRIPT', body: $$[$0 - 1], loc: this._$ }; break; case 3: return { type: 'SCRIPT', body: [], loc: this._$ }; break; case 6: this.$ = [$$[$0 - 1]]; break; case 7: this.$ = $$[$0 - 2].concat([$$[$0 - 1]]); break; case 8: this.$ = $$[$0]; break; case 9: this.$ = $$[$0 - 1].concat([$$[$0]]); break; case 10: this.$ = { type: 'EXPRESSION_BLOCK', body: $$[$0], loc: this._$ }; break; case 11: this.$ = { type: 'IDENTIFIER', value: $$[$0].toLowerCase(), loc: this._$ }; break; case 14: this.$ = [$$[$0]]; break; case 15: this.$ = $$[$0 - 2].concat([$$[$0]]); break; case 16: this.$ = { type: 'CALL_EXPRESSION', callee: $$[$0 - 2], arguments: [], loc: this._$ }; break; case 17: this.$ = { type: 'CALL_EXPRESSION', callee: $$[$0 - 3], arguments: $$[$0 - 1], loc: this._$ }; break; case 18: this.$ = { type: 'LOGICAL_EXPRESSION', left: $$[$0 - 2], right: $$[$0], operator: $$[$0 - 1], loc: this._$ }; break; case 19: case 20: this.$ = { type: 'ASSIGNMENT_EXPRESSION', left: $$[$0 - 2], operator: $$[$0 - 1], right: $$[$0], loc: this._$ }; break; case 21: this.$ = Number($$[$0]); break; case 22: this.$ = Number($$[$0 - 1]); break; case 23: this.$ = Number($$[$0 - 2] + $$[$0 - 1] + $$[$0]); break; case 24: this.$ = Number('0' + $$[$0 - 1] + $$[$0]); break; case 25: this.$ = 0; break; case 26: this.$ = { type: 'NUMBER_LITERAL', value: $$[$0], loc: this._$ }; break; case 27: case 28: case 29: this.$ = { type: 'UNARY_EXPRESSION', value: $$[$0], operator: $$[$0 - 1], loc: this._$ }; break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: this.$ = { type: 'BINARY_EXPRESSION', left: $$[$0 - 2], right: $$[$0], operator: $$[$0 - 1], loc: this._$ }; break; case 41: case 47: this.$ = $$[$0 - 1]; break; } }, table: [{ 3: 1, 4: 2, 5: [1, 4], 6: 3, 9: 13, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 1: [3] }, { 5: [1, 21], 7: 32, 8: $V7, 20: $V8, 28: $V9, 29: $Va, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg, 38: $Vh }, { 5: [1, 34] }, { 1: [2, 3] }, o($Vi, [2, 39]), o($Vi, [2, 40]), { 4: 35, 6: 37, 9: 13, 10: 36, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, o($Vi, [2, 42]), o($Vi, [2, 43]), o($Vi, [2, 44], { 22: [1, 38] }), o($Vi, [2, 45], { 17: [1, 40], 22: [1, 39] }), o($Vi, [2, 46]), o($Vj, [2, 8], { 31: 5, 27: 6, 26: 8, 21: 9, 16: 10, 11: 11, 19: 12, 23: 17, 4: 41, 12: $V0, 17: $V1, 24: $V2, 25: $V3, 28: $V4, 29: $V5, 30: $V6 }), { 4: 42, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 43, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 44, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, o($Vi, [2, 26]), o([5, 8, 15, 17, 18, 20, 22, 28, 29, 32, 33, 34, 35, 36, 37, 38], [2, 11]), o($Vi, [2, 21], { 25: [1, 45] }), o($Vi, [2, 25], { 24: [1, 46] }), { 1: [2, 1] }, { 4: 47, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 48, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 49, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 50, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 51, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 52, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 53, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 54, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 55, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 56, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, o($Vk, [2, 6], { 8: $Vl }), o($Vm, [2, 4]), { 1: [2, 2] }, { 7: 32, 8: $V7, 18: [1, 58], 20: $V8, 28: $V9, 29: $Va, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg, 38: $Vh }, { 18: [1, 59] }, o($Vn, [2, 10]), { 4: 60, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 61, 11: 11, 12: $V0, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, { 4: 65, 6: 37, 9: 13, 10: 66, 11: 11, 12: $V0, 13: 64, 14: 63, 16: 10, 17: $V1, 18: [1, 62], 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, o($Vj, [2, 9], { 7: 67, 8: $V7, 20: $V8, 28: $V9, 29: $Va, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg, 38: $Vh }), o($Vo, [2, 27], { 20: $V8, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg }), o($Vo, [2, 28], { 20: $V8, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg }), o($Vo, [2, 29], { 20: $V8, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg }), o($Vi, [2, 22], { 24: [1, 68] }), o($Vi, [2, 24]), o($Vo, [2, 30], { 20: $V8, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg }), o($Vo, [2, 31], { 20: $V8, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg }), o($Vp, [2, 32], { 20: $V8, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg }), o($Vp, [2, 33], { 20: $V8, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg }), o($Vq, [2, 34], { 20: $V8, 35: $Ve, 36: $Vf }), o($Vr, [2, 35], { 20: $V8 }), o($Vr, [2, 36], { 20: $V8 }), o($Vq, [2, 37], { 20: $V8, 35: $Ve, 36: $Vf }), o($Vs, [2, 38], { 20: $V8, 28: $V9, 29: $Va, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg, 38: $Vh }), o($Vi, [2, 18]), o($Vm, [2, 5]), o($Vi, [2, 41]), o($Vi, [2, 47]), o($Vs, [2, 20], { 20: $V8, 28: $V9, 29: $Va, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg, 38: $Vh }), o($Vs, [2, 19], { 20: $V8, 28: $V9, 29: $Va, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg, 38: $Vh }), o($Vt, [2, 16]), { 15: [1, 70], 18: [1, 69] }, o($Vn, [2, 14]), o($Vn, [2, 12], { 7: 32, 8: $V7, 20: $V8, 28: $V9, 29: $Va, 32: $Vb, 33: $Vc, 34: $Vd, 35: $Ve, 36: $Vf, 37: $Vg, 38: $Vh }), o($Vn, [2, 13]), o($Vk, [2, 7], { 8: $Vl }), o($Vi, [2, 23]), o($Vt, [2, 17]), { 4: 65, 6: 37, 9: 13, 10: 66, 11: 11, 12: $V0, 13: 71, 16: 10, 17: $V1, 19: 12, 21: 9, 23: 17, 24: $V2, 25: $V3, 26: 8, 27: 6, 28: $V4, 29: $V5, 30: $V6, 31: 5 }, o($Vn, [2, 15])], defaultActions: { 4: [2, 3], 21: [2, 1], 34: [2, 2] }, parseError: function parseError(str, hash) { if (hash.recoverable) { this.trace(str); } else { var error = new Error(str); error.hash = hash; throw error; } }, parse: function parse(input) { var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; var args = lstack.slice.call(arguments, 1); var lexer = Object.create(this.lexer); var sharedState = { yy: {} }; for (var k in this.yy) { if (Object.prototype.hasOwnProperty.call(this.yy, k)) { sharedState.yy[k] = this.yy[k]; } } lexer.setInput(input, sharedState.yy); sharedState.yy.lexer = lexer; sharedState.yy.parser = this; if (typeof lexer.yylloc == 'undefined') { lexer.yylloc = {}; } var yyloc = lexer.yylloc; lstack.push(yyloc); var ranges = lexer.options && lexer.options.ranges; if (typeof sharedState.yy.parseError === 'function') { this.parseError = sharedState.yy.parseError; } else { this.parseError = Object.getPrototypeOf(this).parseError; } function popStack(n) { stack.length = stack.length - 2 * n; vstack.length = vstack.length - n; lstack.length = lstack.length - n; } _token_stack: var lex = function () { var token; token = lexer.lex() || EOF; if (typeof token !== 'number') { token = self.symbols_[token] || token; } return token; }; var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; while (true) { state = stack[stack.length - 1]; if (this.defaultActions[state]) { action = this.defaultActions[state]; } else { if (symbol === null || typeof symbol == 'undefined') { symbol = lex(); } action = table[state] && table[state][symbol]; } if (typeof action === 'undefined' || !action.length || !action[0]) { var errStr = ''; expected = []; for (p in table[state]) { if (this.terminals_[p] && p > TERROR) { expected.push('\'' + this.terminals_[p] + '\''); } } if (lexer.showPosition) { errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; } else { errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); } this.parseError(errStr, { text: lexer.match, token: this.terminals_[symbol] || symbol, line: lexer.yylineno, loc: yyloc, expected: expected }); } if (action[0] instanceof Array && action.length > 1) { throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); } switch (action[0]) { case 1: stack.push(symbol); vstack.push(lexer.yytext); lstack.push(lexer.yylloc); stack.push(action[1]); symbol = null; if (!preErrorSymbol) { yyleng = lexer.yyleng; yytext = lexer.yytext; yylineno = lexer.yylineno; yyloc = lexer.yylloc; if (recovering > 0) { recovering--; } } else { symbol = preErrorSymbol; preErrorSymbol = null; } break; case 2: len = this.productions_[action[1]][1]; yyval.$ = vstack[vstack.length - len]; yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; if (ranges) { yyval._$.range = [ lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1] ]; } r = this.performAction.apply(yyval, [ yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack ].concat(args)); if (typeof r !== 'undefined') { return r; } if (len) { stack = stack.slice(0, -1 * len * 2); vstack = vstack.slice(0, -1 * len); lstack = lstack.slice(0, -1 * len); } stack.push(this.productions_[action[1]][0]); vstack.push(yyval.$); lstack.push(yyval._$); newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; stack.push(newState); break; case 3: return true; } } return true; } }; /* generated by jison-lex 0.3.4 */ var lexer = (function () { var lexer = ({ EOF: 1, parseError: function parseError(str, hash) { if (this.yy.parser) { this.yy.parser.parseError(str, hash); } else { throw new Error(str); } }, // resets the lexer, sets new input setInput: function (input, yy) { this.yy = yy || this.yy || {}; this._input = input; this._more = this._backtrack = this.done = false; this.yylineno = this.yyleng = 0; this.yytext = this.matched = this.match = ''; this.conditionStack = ['INITIAL']; this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 }; if (this.options.ranges) { this.yylloc.range = [0, 0]; } this.offset = 0; return this; }, // consumes and returns one char from the input input: function () { var ch = this._input[0]; this.yytext += ch; this.yyleng++; this.offset++; this.match += ch; this.matched += ch; var lines = ch.match(/(?:\r\n?|\n).*/g); if (lines) { this.yylineno++; this.yylloc.last_line++; } else { this.yylloc.last_column++; } if (this.options.ranges) { this.yylloc.range[1]++; } this._input = this._input.slice(1); return ch; }, // unshifts one char (or a string) into the input unput: function (ch) { var len = ch.length; var lines = ch.split(/(?:\r\n?|\n)/g); this._input = ch + this._input; this.yytext = this.yytext.substr(0, this.yytext.length - len); //this.yyleng -= len; this.offset -= len; var oldLines = this.match.split(/(?:\r\n?|\n)/g); this.match = this.match.substr(0, this.match.length - 1); this.matched = this.matched.substr(0, this.matched.length - 1); if (lines.length - 1) { this.yylineno -= lines.length - 1; } var r = this.yylloc.range; this.yylloc = { first_line: this.yylloc.first_line, last_line: this.yylineno + 1, first_column: this.yylloc.first_column, last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len }; if (this.options.ranges) { this.yylloc.range = [r[0], r[0] + this.yyleng - len]; } this.yyleng = this.yytext.length; return this; }, // When called from action, caches matched text and appends it on next action more: function () { this._more = true; return this; }, // When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. reject: function () { if (this.options.backtrack_lexer) { this._backtrack = true; } else { return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); } return this; }, // retain first n characters of the match less: function (n) { this.unput(this.match.slice(n)); }, // displays already matched input, i.e. for error messages pastInput: function () { var past = this.matched.substr(0, this.matched.length - this.match.length); return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); }, // displays upcoming input, i.e. for error messages upcomingInput: function () { var next = this.match; if (next.length < 20) { next += this._input.substr(0, 20 - next.length); } return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); }, // displays the character position where the lexing error occurred, i.e. for error messages showPosition: function () { var pre = this.pastInput(); var c = new Array(pre.length + 1).join("-"); return pre + this.upcomingInput() + "\n" + c + "^"; }, // test the lexed token: return FALSE when not a match, otherwise return token test_match: function (match, indexed_rule) { var token, lines, backup; if (this.options.backtrack_lexer) { // save context backup = { yylineno: this.yylineno, yylloc: { first_line: this.yylloc.first_line, last_line: this.last_line, first_column: this.yylloc.first_column, last_column: this.yylloc.last_column }, yytext: this.yytext, match: this.match, matches: this.matches, matched: this.matched, yyleng: this.yyleng, offset: this.offset, _more: this._more, _input: this._input, yy: this.yy, conditionStack: this.conditionStack.slice(0), done: this.done }; if (this.options.ranges) { backup.yylloc.range = this.yylloc.range.slice(0); } } lines = match[0].match(/(?:\r\n?|\n).*/g); if (lines) { this.yylineno += lines.length; } this.yylloc = { first_line: this.yylloc.last_line, last_line: this.yylineno + 1, first_column: this.yylloc.last_column, last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length }; this.yytext += match[0]; this.match += match[0]; this.matches = match; this.yyleng = this.yytext.length; if (this.options.ranges) { this.yylloc.range = [this.offset, this.offset += this.yyleng]; } this._more = false; this._backtrack = false; this._input = this._input.slice(match[0].length); this.matched += match[0]; token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); if (this.done && this._input) { this.done = false; } if (token) { return token; } else if (this._backtrack) { // recover context for (var k in backup) { this[k] = backup[k]; } return false; // rule action called reject() implying the next rule should be tested instead. } return false; }, // return next match in input next: function () { if (this.done) { return this.EOF; } if (!this._input) { this.done = true; } var token, match, tempMatch, index; if (!this._more) { this.yytext = ''; this.match = ''; } var rules = this._currentRules(); for (var i = 0; i < rules.length; i++) { tempMatch = this._input.match(this.rules[rules[i]]); if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { match = tempMatch; index = i; if (this.options.backtrack_lexer) { token = this.test_match(tempMatch, rules[i]); if (token !== false) { return token; } else if (this._backtrack) { match = false; continue; // rule action called reject() implying a rule MISmatch. } else { // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) return false; } } else if (!this.options.flex) { break; } } } if (match) { token = this.test_match(match, rules[index]); if (token !== false) { return token; } // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) return false; } if (this._input === "") { return this.EOF; } else { return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); } }, // return next match that has a token lex: function lex() { var r = this.next(); if (r) { return r; } else { return this.lex(); } }, // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) begin: function begin(condition) { this.conditionStack.push(condition); }, // pop the previously active lexer condition state off the condition stack popState: function popState() { var n = this.conditionStack.length - 1; if (n > 0) { return this.conditionStack.pop(); } else { return this.conditionStack[0]; } }, // produce the lexer rule set which is active for the currently active lexer condition state _currentRules: function _currentRules() { if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; } else { return this.conditions["INITIAL"].rules; } }, // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available topState: function topState(n) { n = this.conditionStack.length - 1 - Math.abs(n || 0); if (n >= 0) { return this.conditionStack[n]; } else { return "INITIAL"; } }, // alias for begin(condition) pushState: function pushState(condition) { this.begin(condition); }, // return the number of states currently on the stack stateStackSize: function stateStackSize() { return this.conditionStack.length; }, options: {}, performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) { var YYSTATE = YY_START; switch ($avoiding_name_collisions) { case 0: /* skip whitespace */ break; case 1: return 24; break; case 2: return 38; break; case 3: return 22; break; case 4: return 20; break; case 5: return 12; break; case 6: return 5; break; case 7: return yy_.yytext[0]; break; } }, rules: [/^(?:\s+)/, /^(?:[0-9]+)/, /^(?:(==|!=|<=|>=|<|>))/, /^(?:[+\-*/%]?=)/, /^(?:(\&\&)|\|\|)/, /^(?:[a-zA-Z_][a-zA-Z0-9._]*)/, /^(?:$)/, /^(?:.)/], conditions: { "INITIAL": { "rules": [0, 1, 2, 3, 4, 5, 6, 7], "inclusive": true } } }); return lexer; })(); parser.lexer = lexer; function Parser() { this.yy = {}; } Parser.prototype = parser; parser.Parser = Parser; return new Parser; })(); if (true) { exports.parser = parser; exports.Parser = parser.Parser; exports.parse = function () { return parser.parse.apply(parser, arguments); }; exports.main = () => { }; if ( true && __webpack_require__.c[__webpack_require__.s] === module) { exports.main(process.argv.slice(1)); } } //# sourceMappingURL=parser.js.map /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../../webpack/buildin/module.js */ "./node_modules/webpack/buildin/module.js")(module), __webpack_require__(/*! ./../../../process/browser.js */ "./node_modules/process/browser.js"))) /***/ }), /***/ "./node_modules/eel-wasm/dist/src/astUtils.js": /*!****************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/astUtils.js ***! \****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const CHILDREN = { ASSIGNMENT_EXPRESSION: [ { type: "NODE", key: "right" }, ], SCRIPT: [{ type: "ARRAY", key: "body" }], EXPRESSION_BLOCK: [{ type: "ARRAY", key: "body" }], UNARY_EXPRESSION: [{ type: "NODE", key: "value" }], NUMBER_LITERAL: [], IDENTIFIER: [], CALL_EXPRESSION: [ { type: "ARRAY", key: "arguments" }, { type: "NODE", key: "callee" }, ], BINARY_EXPRESSION: [ { type: "NODE", key: "left" }, { type: "NODE", key: "right" }, ], LOGICAL_EXPRESSION: [ { type: "NODE", key: "left" }, { type: "NODE", key: "right" }, ], }; function mapAst(ast, cb) { const children = CHILDREN[ast.type]; let newAst = ast; if (children == null) { throw new Error(`Unknown children definition for ${ast.type}`); } children.forEach(child => { if (child.type === "NODE") { const orignalChild = ast[child.key]; const newChild = mapAst(orignalChild, cb); if (newChild !== orignalChild) { newAst = Object.assign(Object.assign({}, newAst), { [child.key]: newChild }); } } else if (child.type === "ARRAY") { const orignalChildren = ast[child.key]; const newChildren = orignalChildren.map(originalChild => mapAst(originalChild, cb)); const childrenHaveChanged = orignalChildren.some((child, i) => child !== newChildren[i]); if (childrenHaveChanged) { newAst = Object.assign(Object.assign({}, newAst), { [child.key]: newChildren }); } } }); return cb(newAst); } exports.mapAst = mapAst; //# sourceMappingURL=astUtils.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/compiler.js": /*!****************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/compiler.js ***! \****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const parser_1 = __webpack_require__(/*! ./parser */ "./node_modules/eel-wasm/dist/src/parser.js"); const emitter_1 = __webpack_require__(/*! ./emitter */ "./node_modules/eel-wasm/dist/src/emitter.js"); const encoding_1 = __webpack_require__(/*! ./encoding */ "./node_modules/eel-wasm/dist/src/encoding.js"); const shims_1 = __importDefault(__webpack_require__(/*! ./shims */ "./node_modules/eel-wasm/dist/src/shims.js")); const Utils = __importStar(__webpack_require__(/*! ./utils */ "./node_modules/eel-wasm/dist/src/utils.js")); const wasmFunctions_1 = __webpack_require__(/*! ./wasmFunctions */ "./node_modules/eel-wasm/dist/src/wasmFunctions.js"); const constants_1 = __webpack_require__(/*! ./constants */ "./node_modules/eel-wasm/dist/src/constants.js"); function compileModule({ pools, functions: funcs, eelVersion = 2, preParsed = false, }) { if (Object.keys(pools).includes("shims")) { throw new Error('You may not name a pool "shims". "shims" is reserved for injected JavaScript functions.'); } // Collect all the globals that we expect to get as imports. const importedVars = []; Object.entries(pools).forEach(([poolName, pool]) => { pool.forEach(variableName => { importedVars.push([poolName, variableName]); }); }); // Ensure all the imported globals get the first ids. const varResolver = new Utils.ScopedIdMap(); importedVars.forEach(([poolName, variableName]) => { varResolver.get(poolName, variableName); }); const functionImports = Object.entries(shims_1.default).map(([name, func]) => { return { args: new Array(func.length).fill(null).map(_ => encoding_1.VAL_TYPE.f64), // Shims implicitly always return a number returns: [encoding_1.VAL_TYPE.f64], name, }; }); const localFuncOrder = []; const moduleFuncs = []; Object.entries(funcs).forEach(([name, { pool, code }]) => { if (pools[pool] == null) { const poolsList = Object.keys(pools); if (poolsList.length === 0) { throw new Error(`The function "${name}" was declared as using a variable ` + `pool named "${pool}" but no pools were defined.`); } throw new Error(`The function "${name}" was declared as using a variable ` + `pool named "${pool}" which is not among the variable ` + `pools defined. The defined variable pools are: ` + `${Utils.formatList(poolsList)}.`); } const ast = preParsed ? code : parser_1.parse(code); if (typeof ast === "string") { // TODO: Change the API so this can be enforced by types throw new Error("Got passed unparsed code without setting the preParsed flag"); } if (ast.type !== "SCRIPT") { throw new Error("Invalid AST"); } if (ast.body.length === 0) { return; } const localVariables = []; const context = { resolveVar: name => { // The `reg00`-`reg99` variables are special in that they are shared between all pools. if (/^reg\d\d$/.test(name)) { return varResolver.get(null, name); } return varResolver.get(pool, name); }, resolveLocal: type => { // TODO: We could provide a way for the emitter to release a local // variable so that we can reuse it, much in the same way a traditional // compiler does in register allocation. localVariables.push(type); return localVariables.length - 1; }, resolveFunc: name => { // If this is a shim, return the shim index. const shimdex = functionImports.findIndex(func => func.name === name); if (shimdex !== -1) { const call = encoding_1.op.call(shimdex); if (name === "rand" && eelVersion === 1) { return [...call, encoding_1.op.f64_floor]; } return call; } // If it's not a shim and it's not a defined function, return null. // The emitter will generate a nice error. if (wasmFunctions_1.localFuncMap[name] == null) { return null; } let index = localFuncOrder.indexOf(name); if (index === -1) { localFuncOrder.push(name); index = localFuncOrder.length - 1; } return encoding_1.op.call(index + functionImports.length); }, rawSource: code, }; const binary = emitter_1.emit(ast, context); moduleFuncs.push({ binary, exportName: name, args: [], returns: [], localVariables, }); }); const localFuncs = localFuncOrder.map(name => { const func = wasmFunctions_1.localFuncMap[name]; // This check is technicaly redundant since we check inside resolveLocalFunc // in the compiler context. It's here just to catch potential compiler bugs. if (func == null) { throw new Error(`Undefined local function "${name}"`); } return func; }); // Given a function definition, return a hashable string representation of its signature. const getSignatureKey = (func) => { return [...func.args, "|", ...func.returns].join("-"); }; // https://webassembly.github.io/spec/core/binary/modules.html#type-section const types = []; const typeIndexByKey = new Map(); [...functionImports, ...localFuncs, ...moduleFuncs].forEach(func => { const key = getSignatureKey(func); if (typeIndexByKey.has(key)) { return; } types.push([ encoding_1.FUNCTION_TYPE, ...encoding_1.encodeFlatVector(func.args), ...encoding_1.encodeFlatVector(func.returns), ]); typeIndexByKey.set(key, types.length - 1); }); function getTypeIndex(func) { const key = getSignatureKey(func); const typeIndex = typeIndexByKey.get(key); if (typeIndex == null) { throw new Error(`Failed to get a type index for key ${key}`); } return typeIndex; } // https://webassembly.github.io/spec/core/binary/modules.html#import-section const imports = [ ...importedVars.map(([namespace, name]) => { return [ ...encoding_1.encodeString(namespace), ...encoding_1.encodeString(name), ...[encoding_1.GLOBAL_TYPE, encoding_1.VAL_TYPE.f64, encoding_1.MUTABILITY.var], ]; }), ...functionImports.map((func, i) => { const typeIndex = getTypeIndex(func); return [ ...encoding_1.encodeString("shims"), ...encoding_1.encodeString(func.name), ...[encoding_1.TYPE_IDX, ...encoding_1.unsignedLEB128(typeIndex)], ]; }), ]; // https://webassembly.github.io/spec/core/binary/modules.html#function-section // // > Functions are referenced through function indices, starting with the smallest // > index not referencing a function import. const functions = [...localFuncs, ...moduleFuncs].map(func => { const typeIndex = getTypeIndex(func); return encoding_1.unsignedLEB128(typeIndex); }); const memories = [ // Only one memory [ 0x01, ...encoding_1.unsignedLEB128(constants_1.WASM_MEMORY_SIZE), ...encoding_1.unsignedLEB128(constants_1.WASM_MEMORY_SIZE), ], ]; // https://webassembly.github.io/spec/core/binary/modules.html#global-section const globalCount = varResolver.size() - importedVars.length; const globals = Utils.times(globalCount, () => { return [ encoding_1.VAL_TYPE.f64, encoding_1.MUTABILITY.var, ...encoding_1.op.f64_const(0), encoding_1.op.end, ]; }); // https://webassembly.github.io/spec/core/binary/modules.html#binary-exportsec const xports = [...moduleFuncs].map((func, i) => { const funcIndex = i + functionImports.length + localFuncs.length; return [ ...encoding_1.encodeString(func.exportName), encoding_1.EXPORT_TYPE.FUNC, ...encoding_1.unsignedLEB128(funcIndex), ]; }); /* Uncomment this to expose memory xports.push([ ...encodeString("memory"), EXPORT_TYPE.MEMORY, ...unsignedLEB128(0), ]); */ // https://webassembly.github.io/spec/core/binary/modules.html#code-section const codes = [...localFuncs, ...moduleFuncs].map(func => { var _a; // TODO: We could collapose consecutive types here, or even move to a two // pass approach where ids are resolved after the emitter is run. const localTypes = ((_a = func.localVariables) !== null && _a !== void 0 ? _a : []).map(type => { return [...encoding_1.unsignedLEB128(1), type]; }); // It's a bit odd that every other section is an array of arrays and this // one is an array of vectors. The spec says this is so that when navigating // the binary functions can be skipped efficiently. return encoding_1.encodeFlatVector([ ...encoding_1.encodeNestedVector(localTypes), ...func.binary, encoding_1.op.end, ]); }); return new Uint8Array([ // Magic module header ...encoding_1.MAGIC, // Version number ...encoding_1.WASM_VERSION, ...encoding_1.encodeSection(encoding_1.SECTION.TYPE, types), ...encoding_1.encodeSection(encoding_1.SECTION.IMPORT, imports), ...encoding_1.encodeSection(encoding_1.SECTION.FUNC, functions), ...encoding_1.encodeSection(encoding_1.SECTION.MEMORY, memories), ...encoding_1.encodeSection(encoding_1.SECTION.GLOBAL, globals), ...encoding_1.encodeSection(encoding_1.SECTION.EXPORT, xports), ...encoding_1.encodeSection(encoding_1.SECTION.CODE, codes), ]); } exports.compileModule = compileModule; //# sourceMappingURL=compiler.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/constants.js": /*!*****************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/constants.js ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // https://webassembly.github.io/spec/core/exec/runtime.html#page-size const WASM_PAGE_SIZE = 65536; const BYTES_PER_F64 = 8; const BUFFER_COUNT = 2; // https://github.com/WACUP/vis_milk2/blob/de9625a89e724afe23ed273b96b8e48496095b6c/ns-eel2/ns-eel.h#L136 exports.MAX_LOOP_COUNT = 1048576; // The number of items allowed in each buffer (megabuf/gmegabuf). // https://github.com/WACUP/vis_milk2/blob/de9625a89e724afe23ed273b96b8e48496095b6c/ns-eel2/ns-eel.h#L145 exports.BUFFER_SIZE = 65536 * 128; exports.WASM_MEMORY_SIZE = Math.ceil((exports.BUFFER_SIZE * BYTES_PER_F64 * BUFFER_COUNT) / WASM_PAGE_SIZE); //# sourceMappingURL=constants.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/emitter.js": /*!***************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/emitter.js ***! \***************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const encoding_1 = __webpack_require__(/*! ./encoding */ "./node_modules/eel-wasm/dist/src/encoding.js"); const shims_1 = __importDefault(__webpack_require__(/*! ./shims */ "./node_modules/eel-wasm/dist/src/shims.js")); const errorUtils_1 = __webpack_require__(/*! ./errorUtils */ "./node_modules/eel-wasm/dist/src/errorUtils.js"); const wasmFunctions_1 = __webpack_require__(/*! ./wasmFunctions */ "./node_modules/eel-wasm/dist/src/wasmFunctions.js"); const utils_1 = __webpack_require__(/*! ./utils */ "./node_modules/eel-wasm/dist/src/utils.js"); const constants_1 = __webpack_require__(/*! ./constants */ "./node_modules/eel-wasm/dist/src/constants.js"); function emit(ast, context) { var _a, _b, _c; switch (ast.type) { case "SCRIPT": { const body = ast.body.map((statement, i) => { return [...emit(statement, context), encoding_1.op.drop]; }); return utils_1.flatten(body); } case "EXPRESSION_BLOCK": { return emitExpressionBlock(ast.body, context); } case "BINARY_EXPRESSION": { const left = emit(ast.left, context); const right = emit(ast.right, context); const operatorToOps = { "+": [encoding_1.op.f64_add], "-": [encoding_1.op.f64_sub], "*": [encoding_1.op.f64_mul], "/": context.resolveFunc("div"), "%": context.resolveFunc("mod"), "|": context.resolveFunc("bitwiseOr"), "&": context.resolveFunc("bitwiseAnd"), "^": context.resolveFunc("pow"), // Comparison operators "==": [encoding_1.op.f64_sub, ...encoding_1.IS_ZEROISH, encoding_1.op.f64_convert_i32_s], "!=": [encoding_1.op.f64_sub, ...encoding_1.IS_NOT_ZEROISH, encoding_1.op.f64_convert_i32_s], "<": [encoding_1.op.f64_lt, encoding_1.op.f64_convert_i32_s], ">": [encoding_1.op.f64_gt, encoding_1.op.f64_convert_i32_s], "<=": [encoding_1.op.f64_le, encoding_1.op.f64_convert_i32_s], ">=": [encoding_1.op.f64_ge, encoding_1.op.f64_convert_i32_s], }; const code = operatorToOps[ast.operator]; if (code == null) { throw errorUtils_1.createCompilerError(`Unknown binary expression operator ${ast.operator}`, ast.loc, context.rawSource); } return [...left, ...right, ...code]; } case "CALL_EXPRESSION": { const functionName = ast.callee.value; // Destructure this so that TypeScript knows it won't get mutated. const argList = ast.arguments; const assertArity = (arity) => { if (argList.length < arity) { throw errorUtils_1.createUserError(`Too few arguments passed to \`${functionName}()\`. Expected ${arity} but only got ${argList.length}.`, ast.loc, context.rawSource); } if (argList.length > arity) { throw errorUtils_1.createUserError(`Too many arguments passed to \`${functionName}()\`. Expected ${arity} but got ${argList.length}.`, argList[arity].loc, context.rawSource); } }; // Some functions have special behavior switch (functionName) { case "exec2": assertArity(2); return emitExpressionBlock(ast.arguments, context); case "exec3": assertArity(3); return emitExpressionBlock(ast.arguments, context); case "if": assertArity(3); const [test, consiquent, alternate] = ast.arguments; return emitConditional(test, consiquent, alternate, context); case "while": assertArity(1); return emitWhile(ast.arguments[0], context); case "loop": assertArity(2); return emitLoop(ast.arguments[0], ast.arguments[1], context); case "megabuf": case "gmegabuf": assertArity(1); const index = context.resolveLocal(encoding_1.VAL_TYPE.i32); return [ ...emit(ast.arguments[0], context), ...((_a = context.resolveFunc("_getBufferIndex")) !== null && _a !== void 0 ? _a : []), ...encoding_1.op.local_tee(index), ...encoding_1.op.i32_const(-1), encoding_1.op.i32_ne, // STACK: [in range] ...encoding_1.op.if(encoding_1.BLOCK.f64), ...encoding_1.op.local_get(index), ...encoding_1.op.f64_load(3, emitAddMemoryOffset(functionName)), encoding_1.op.else, ...encoding_1.op.f64_const(0), encoding_1.op.end, ]; case "assign": assertArity(2); const variableIdentifier = ast.arguments[0]; if (variableIdentifier.type != "IDENTIFIER") { throw errorUtils_1.createUserError("Expected the first argument of `assign()` to be an identifier.", variableIdentifier.loc, context.rawSource); } const resolvedName = context.resolveVar(variableIdentifier.value); return [ ...emit(ast.arguments[1], context), ...encoding_1.op.global_set(resolvedName), ...encoding_1.op.global_get(resolvedName), ]; } // Function calls which can be linlined const args = utils_1.flatten(ast.arguments.map(node => emit(node, context))); // This is just a continuation of the above switch statement, but it's for functions which all parse their args the same. switch (functionName) { case "abs": assertArity(1); return [...args, encoding_1.op.f64_abs]; case "sqrt": assertArity(1); return [...args, encoding_1.op.f64_abs, encoding_1.op.f64_sqrt]; case "int": assertArity(1); return [...args, encoding_1.op.f64_floor]; case "min": assertArity(2); return [...args, encoding_1.op.f64_min]; case "max": assertArity(2); return [...args, encoding_1.op.f64_max]; case "above": assertArity(2); return [...args, encoding_1.op.f64_gt, encoding_1.op.f64_convert_i32_s]; case "below": assertArity(2); return [...args, encoding_1.op.f64_lt, encoding_1.op.f64_convert_i32_s]; case "equal": assertArity(2); return [...args, encoding_1.op.f64_sub, ...encoding_1.IS_ZEROISH, encoding_1.op.f64_convert_i32_s]; case "bnot": assertArity(1); return [...args, ...encoding_1.IS_ZEROISH, encoding_1.op.f64_convert_i32_s]; case "floor": assertArity(1); return [...args, encoding_1.op.f64_floor]; case "ceil": assertArity(1); return [...args, encoding_1.op.f64_ceil]; } const invocation = context.resolveFunc(functionName); if (invocation == null || // Ensure this isn't a private function. This is a bit awkward becuase // Eel does implement some _ functions but while they are _intended_ to be // private, they accidentally expose them. We should find a cleaner way // to defining user accessible functions vs utility functions used by // the compiler. functionName.startsWith("_")) { throw errorUtils_1.createUserError(`"${functionName}" is not defined.`, ast.callee.loc, context.rawSource); } if (shims_1.default[functionName] != null) { assertArity(shims_1.default[functionName].length); } else if (wasmFunctions_1.localFuncMap[functionName] != null) { assertArity(wasmFunctions_1.localFuncMap[functionName].args.length); } else { throw errorUtils_1.createCompilerError(`Missing arity information for the function \`${functionName}()\``, ast.callee.loc, context.rawSource); } return [...args, ...invocation]; } case "ASSIGNMENT_EXPRESSION": { const { left } = ast; const rightCode = emit(ast.right, context); const mutationCode = getAssignmentOperatorMutation(ast, context); if (left.type === "IDENTIFIER") { const resolvedName = context.resolveVar(left.value); // TODO: In lots of cases we don't care about the return value. In those // cases we should try to find a way to omit the `get/drop` combo. // Peephole optimization seems to be the conventional way to do this. // https://en.wikipedia.org/wiki/Peephole_optimization const get = encoding_1.op.global_get(resolvedName); const set = encoding_1.op.global_set(resolvedName); // `=` is a special case in that it does not need the original value. if (mutationCode === null) { return [...rightCode, ...set, ...get]; } return [...get, ...rightCode, ...mutationCode, ...set, ...get]; } if (left.type !== "CALL_EXPRESSION") { throw errorUtils_1.createCompilerError( // @ts-ignore This is a guard in case the parser has an error `Unexpected left hand side type for assignment: ${left.type}`, ast.loc, context.rawSource); } // Special assignment case for `megabuf(n) = e` and `gmegabuf(n) = e`. const localIndex = context.resolveLocal(encoding_1.VAL_TYPE.i32); if (left.arguments.length !== 1) { throw errorUtils_1.createUserError(`Expected 1 argument when assinging to a buffer but got ${left.arguments.length}.`, left.arguments.length === 0 ? left.loc : left.arguments[1].loc, context.rawSource); } const bufferName = left.callee.value; if (bufferName !== "gmegabuf" && bufferName !== "megabuf") { throw errorUtils_1.createUserError("The only function calls which may be assigned to are `gmegabuf()` and `megabuf()`.", left.callee.loc, context.rawSource); } const addOffset = emitAddMemoryOffset(bufferName); if (mutationCode === null) { // TODO: Move this to wasmFunctions once we know how to call functions // from within functions (need to get the offset). const unnormalizedIndex = context.resolveLocal(encoding_1.VAL_TYPE.i32); const rightValue = context.resolveLocal(encoding_1.VAL_TYPE.f64); return [ // Emit the right hand side unconditionally to ensure it always runs. ...rightCode, ...encoding_1.op.local_set(rightValue), ...emit(left.arguments[0], context), ...((_b = context.resolveFunc("_getBufferIndex")) !== null && _b !== void 0 ? _b : []), ...encoding_1.op.local_tee(unnormalizedIndex), ...encoding_1.op.i32_const(0), encoding_1.op.i32_lt_s, // STACK: [is the index out of range?] ...encoding_1.op.if(encoding_1.BLOCK.f64), ...encoding_1.op.f64_const(0), encoding_1.op.else, ...encoding_1.op.local_get(unnormalizedIndex), ...encoding_1.op.local_tee(localIndex), // STACK: [buffer index] ...encoding_1.op.local_get(rightValue), // STACK: [buffer index, right] ...encoding_1.op.f64_store(3, addOffset), // STACK: [] ...encoding_1.op.local_get(rightValue), // STACK: [Right/Buffer value] encoding_1.op.end, ]; } // TODO: Move this to wasmFunctions once we know how to call functions // from within functions (need to get the offset). const index = context.resolveLocal(encoding_1.VAL_TYPE.i32); const inBounds = context.resolveLocal(encoding_1.VAL_TYPE.i32); const rightValue = context.resolveLocal(encoding_1.VAL_TYPE.f64); const result = context.resolveLocal(encoding_1.VAL_TYPE.f64); return [ ...rightCode, ...encoding_1.op.local_set(rightValue), ...emit(left.arguments[0], context), ...((_c = context.resolveFunc("_getBufferIndex")) !== null && _c !== void 0 ? _c : []), ...encoding_1.op.local_tee(index), // STACK: [index] ...encoding_1.op.i32_const(-1), encoding_1.op.i32_ne, ...encoding_1.op.local_tee(inBounds), ...encoding_1.op.if(encoding_1.BLOCK.f64), ...encoding_1.op.local_get(index), ...encoding_1.op.f64_load(3, addOffset), encoding_1.op.else, ...encoding_1.op.f64_const(0), encoding_1.op.end, // STACK: [current value from memory || 0] // Apply the mutation ...encoding_1.op.local_get(rightValue), ...mutationCode, ...encoding_1.op.local_tee(result), // STACK: [new value] ...encoding_1.op.local_get(inBounds), ...encoding_1.op.if(encoding_1.BLOCK.void), ...encoding_1.op.local_get(index), ...encoding_1.op.local_get(result), ...encoding_1.op.f64_store(3, addOffset), encoding_1.op.end, ]; } case "LOGICAL_EXPRESSION": { const left = emit(ast.left, context); const right = emit(ast.right, context); const behaviorMap = { "&&": { comparison: encoding_1.IS_ZEROISH, shortCircutValue: 0, }, "||": { comparison: encoding_1.IS_NOT_ZEROISH, shortCircutValue: 1, }, }; const behavior = behaviorMap[ast.operator]; if (behavior == null) { throw errorUtils_1.createCompilerError(`Unknown logical expression operator ${ast.operator}`, ast.loc, context.rawSource); } const { comparison, shortCircutValue } = behavior; return [ ...left, ...comparison, ...encoding_1.op.if(encoding_1.BLOCK.f64), ...encoding_1.op.f64_const(shortCircutValue), encoding_1.op.else, ...right, ...encoding_1.IS_NOT_ZEROISH, encoding_1.op.f64_convert_i32_s, encoding_1.op.end, ]; } case "UNARY_EXPRESSION": { const value = emit(ast.value, context); const operatorToCode = { "-": [encoding_1.op.f64_neg], "+": [], "!": [...encoding_1.IS_ZEROISH, encoding_1.op.f64_convert_i32_s], }; const code = operatorToCode[ast.operator]; if (code == null) { throw errorUtils_1.createCompilerError(`Unknown logical unary operator ${ast.operator}`, ast.loc, context.rawSource); } return [...value, ...code]; } case "IDENTIFIER": const variableName = ast.value; // TODO: It's a bit odd that not every IDENTIFIER node gets emitted. In // function calls and assignments we just peek at the name and never emit // it. return encoding_1.op.global_get(context.resolveVar(variableName)); case "NUMBER_LITERAL": return encoding_1.op.f64_const(ast.value); default: throw errorUtils_1.createCompilerError( // @ts-ignore This runtime check is here because the caller may not be type-checked `Unknown AST node type ${ast.type}`, // @ts-ignore This runtime check is here because the caller may not be type-checked ast.loc, context.rawSource); } } exports.emit = emit; function emitExpressionBlock(body, context) { const statements = body.map((statement, i) => { return emit(statement, context); }); return utils_1.flatten(utils_1.arrayJoin(statements, [encoding_1.op.drop])); } function emitWhile(expression, context) { const body = emit(expression, context); const iterationCount = context.resolveLocal(encoding_1.VAL_TYPE.i32); return [ ...encoding_1.op.i32_const(0), ...encoding_1.op.local_set(iterationCount), ...encoding_1.op.loop(encoding_1.BLOCK.void), // Increment and check loop count ...encoding_1.op.local_get(iterationCount), ...encoding_1.op.i32_const(1), encoding_1.op.i32_add, ...encoding_1.op.local_tee(iterationCount), // STACK: [iteration count] ...encoding_1.op.i32_const(constants_1.MAX_LOOP_COUNT), encoding_1.op.i32_lt_u, // STACK: [loop in range] ...body, ...encoding_1.IS_NOT_ZEROISH, // STACK: [loop in range, body is truthy] encoding_1.op.i32_and, // STACK: [can continue] ...encoding_1.op.br_if(0), encoding_1.op.end, ...encoding_1.op.f64_const(0), ]; } function emitLoop(count, expression, context) { const body = emit(expression, context); const localIndex = context.resolveLocal(encoding_1.VAL_TYPE.i32); return [ ...encoding_1.op.block(encoding_1.BLOCK.void), // Assign the count to a variable ...emit(count, context), encoding_1.op.i32_trunc_f64_s, ...encoding_1.op.local_tee(localIndex), ...encoding_1.op.i32_const(0), encoding_1.op.i32_le_s, ...encoding_1.op.br_if(1), ...encoding_1.op.loop(encoding_1.BLOCK.void), // Run the body ...body, encoding_1.op.drop, // Decrement the count ...encoding_1.op.local_get(localIndex), ...encoding_1.op.i32_const(1), encoding_1.op.i32_sub, ...encoding_1.op.local_tee(localIndex), ...encoding_1.op.i32_const(0), encoding_1.op.i32_ne, ...encoding_1.op.br_if(0), encoding_1.op.end, encoding_1.op.end, ...encoding_1.op.f64_const(0), ]; } function emitConditional(test, consiquent, alternate, context) { // TODO: In some cases https://webassembly.studio/ compiles these to use `select`. // Is that an optimization that we might want as well? return [ ...emit(test, context), ...encoding_1.IS_NOT_ZEROISH, ...encoding_1.op.if(encoding_1.BLOCK.f64), ...emit(consiquent, context), encoding_1.op.else, ...emit(alternate, context), encoding_1.op.end, ]; } // There are two sections of memory. This function emits code to add the correct // offset to an i32 index already on the stack. function emitAddMemoryOffset(name) { switch (name) { case "gmegabuf": return constants_1.BUFFER_SIZE * 8; case "megabuf": return 0; } } function getAssignmentOperatorMutation(ast, context) { const operatorToCode = { "+=": [encoding_1.op.f64_add], "-=": [encoding_1.op.f64_sub], "*=": [encoding_1.op.f64_mul], "/=": [encoding_1.op.f64_div], "%=": context.resolveFunc("mod"), "=": null, }; const operatorCode = operatorToCode[ast.operator]; if (operatorCode === undefined) { throw errorUtils_1.createCompilerError(`Unknown assignment operator "${ast.operator}"`, ast.loc, context.rawSource); } return operatorCode; } //# sourceMappingURL=emitter.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/encoding.js": /*!****************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/encoding.js ***! \****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const ieee754 = __importStar(__webpack_require__(/*! ./ieee754 */ "./node_modules/eel-wasm/dist/src/ieee754.js")); const utils_1 = __webpack_require__(/*! ./utils */ "./node_modules/eel-wasm/dist/src/utils.js"); exports.MAGIC = [0x00, 0x61, 0x73, 0x6d]; exports.WASM_VERSION = [0x01, 0x00, 0x00, 0x00]; exports.EPSILON = 0.00001; // An intial attempt to construct a Wasm binary by hand. /* 0 custom section 1 type section 2 import section 3 function section 4 table section 5 memory section 6 global section 7 export section 8 start section 9 element section 10 code section 11 data section */ // https://webassembly.github.io/spec/core/binary/modules.html#sections exports.SECTION = { TYPE: 1, IMPORT: 2, FUNC: 3, MEMORY: 5, GLOBAL: 6, EXPORT: 7, CODE: 10, }; exports.EXPORT_TYPE = { FUNC: 0x00, TABLE: 0x01, MEMORY: 0x02, GLOBAL: 0x03, }; exports.op = { /* * Control Instructions * https://webassembly.github.io/spec/core/binary/instructions.html#control-instructions */ // unreachable: 0x00, // nop: 0x01, block: (blockType) => [0x02, blockType], loop: (blockType) => [0x03, blockType], if: (retType) => [0x04, retType], else: 0x05, end: 0x0b, // br: (i: number) => [0x0c, ...signedLEB128(i)], br_if: (i) => [0x0d, ...unsignedLEB128(i)], // br_table: 0x0d, // return: 0x0f, call: (i) => [0x10, ...unsignedLEB128(i)], // call_indirect: 0x11, /* * Parametric Instructions * https://webassembly.github.io/spec/core/binary/instructions.html#parametric-instructions */ drop: 0x1a, select: 0x1b, /* * Variable Instructions * https://webassembly.github.io/spec/core/binary/instructions.html#variable-instructions */ local_get: (i) => [0x20, ...unsignedLEB128(i)], local_set: (i) => [0x21, ...unsignedLEB128(i)], local_tee: (i) => [0x22, ...unsignedLEB128(i)], global_get: (i) => [0x23, ...unsignedLEB128(i)], global_set: (i) => [0x24, ...unsignedLEB128(i)], /* * Memory Instructions * https://webassembly.github.io/spec/core/binary/instructions.html#memory-instructions */ f64_load: (align, offset) => [ 0x2b, ...unsignedLEB128(align), ...unsignedLEB128(offset), ], f64_store: (align, offset) => [ 0x39, ...unsignedLEB128(align), ...unsignedLEB128(offset), ], /* * Numeric Instructions * https://webassembly.github.io/spec/core/binary/instructions.html#numeric-instructions */ i32_const: (i) => [0x41, ...signedLEB128(i)], // i64_const: 0x42, // f32_const: 0x43, f64_const: (i) => [0x44, ...encodef64(i)], i32_eqz: 0x45, // i32_eq: 0x46, i32_ne: 0x47, i32_lt_s: 0x48, i32_lt_u: 0x49, i32_gt_s: 0x4a, // i32_gt_u: 0x4b, i32_le_s: 0x4c, i32_le_u: 0x4d, i32_ge_s: 0x4e, // i32_ge_u: 0x4f, // [0x50...0x5a] i64 // [0x5b...0x60] f32 f64_eq: 0x61, f64_ne: 0x62, f64_lt: 0x63, f64_gt: 0x64, f64_le: 0x65, f64_ge: 0x66, // i32_clz: 0x67, // i32_ctz: 0x68, // i32_popcnt: 0x69, i32_add: 0x6a, i32_sub: 0x6b, i32_mul: 0x6c, // i32_div_s: 0x6d, // i32_div_u: 0x6e, i32_rem_s: 0x6f, // i32_rem_u: 0x70, i32_and: 0x71, i32_or: 0x72, // [0x73...0x78] More i32 // [0x79...0x8a] More i64 i64_rem_s: 0x81, i64_and: 0x83, i64_or: 0x84, // [0x8b...0x98] More f32 f64_abs: 0x99, f64_neg: 0x9a, f64_ceil: 0x9b, f64_floor: 0x9c, // f64_trunc: 0x9d, // f64_nearest: 0x9e, f64_sqrt: 0x9f, f64_add: 0xa0, f64_sub: 0xa1, f64_mul: 0xa2, f64_div: 0xa3, f64_min: 0xa4, f64_max: 0xa5, // f64_copysign: 0xa6, i32_trunc_f64_s: 0xaa, i32_trunc_f64_u: 0xab, i64_trunc_s_f64: 0xb0, f64_convert_i64_s: 0xb9, f64_convert_i32_s: 0xb7, }; // https://webassembly.github.io/spec/core/binary/instructions.html#binary-blocktype exports.VAL_TYPE = { i32: 0x7f, i64: 0x7e, f32: 0x7d, f64: 0x7c, }; exports.MUTABILITY = { const: 0x00, var: 0x01, }; exports.BLOCK = { void: 0x40, i32: 0x7f, i64: 0x7e, f32: 0x7d, f64: 0x7c, }; // http://webassembly.github.io/spec/core/binary/types.html#function-types exports.FUNCTION_TYPE = 0x60; // I think these might actually be specific to importdesc exports.MEMORY_IDX = 0x02; exports.GLOBAL_TYPE = 0x03; exports.TYPE_IDX = 0x00; // Takes an f64 on the stack and leaves an int32 boolean representing if it's // within epsilon of zero. exports.IS_ZEROISH = [ exports.op.f64_abs, ...exports.op.f64_const(exports.EPSILON), exports.op.f64_lt, ]; exports.IS_NOT_ZEROISH = [ exports.op.f64_abs, ...exports.op.f64_const(exports.EPSILON), exports.op.f64_gt, ]; // f64 function encodef64(num) { const arr = new Uint8Array(8); ieee754.write(arr, num); return arr; } exports.encodef64 = encodef64; exports.encodeString = (str) => [str.length].concat(str.split("").map(s => s.charCodeAt(0))); function unsignedLEB128(n) { const buffer = []; do { let byte = n & 0x7f; n >>>= 7; if (n !== 0) { byte |= 0x80; } buffer.push(byte); } while (n !== 0); return buffer; } exports.unsignedLEB128 = unsignedLEB128; // https://github.com/shmishtopher/wasm-LEB128/blob/2f1039636e758293e571f996e8012c4d69f4b58f/lib/index.js#L6 function signedLEB128(value) { let bytes = []; let byte = 0x00; let size = Math.ceil(Math.log2(Math.abs(value))); let negative = value < 0; let more = true; while (more) { byte = value & 127; value = value >> 7; if (negative) { value = value | -(1 << (size - 7)); } if ((value == 0 && (byte & 0x40) == 0) || (value == -1 && (byte & 0x40) == 0x40)) { more = false; } else { byte = byte | 128; } bytes.push(byte); } return bytes; } exports.signedLEB128 = signedLEB128; // https://webassembly.github.io/spec/core/binary/conventions.html#binary-vec // Vectors are encoded with their length followed by their element sequence exports.encodeFlatVector = (data) => unsignedLEB128(data.length).concat(data); exports.encodeNestedVector = (data) => unsignedLEB128(data.length).concat(utils_1.flatten(data)); // subSections is an array of arrays function encodeSection(type, subSections) { // Sections are all optional, so if we get an empty vector of subSections, we // can omit the whole section. if (subSections.length === 0) { return []; } // The size of this vector is not needed for decoding, but can be // used to skip sections when navigating through a binary. // TODO: Remove this assertion once we are more confident in our output. const vec = exports.encodeFlatVector(exports.encodeNestedVector(subSections)); vec.unshift(type); return vec; } exports.encodeSection = encodeSection; //# sourceMappingURL=encoding.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/envParser.js": /*!*****************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/envParser.js ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { // This module is in charge of selecting either the pre-built module or the one // that builds it a runtime with jison. let parserImpl = __webpack_require__(/*! ../build/parser */ "./node_modules/eel-wasm/dist/build/parser.js"); /* let parserImpl = null; // Always use the dynamic one, while we figure out why the built one doens't work. if (process.env.NODE_ENV === "production") { parserImpl = require("../build/parser"); } else { parserImpl = require("../tools/buildParser"); } */ module.exports = { parse: parserImpl.parse }; //# sourceMappingURL=envParser.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/errorUtils.js": /*!******************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/errorUtils.js ***! \******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = __webpack_require__(/*! ./utils */ "./node_modules/eel-wasm/dist/src/utils.js"); /* Build up a string showing a formatted source location in context with line numbers. * * 2 | z = sqr(y, 10); * > 3 | x = wat(); * | ^^^ * 4 | y = 100; */ function printLoc(loc, rawSource, contextLines = 1) { const firstIndex = Math.max(loc.first_line - 1 - contextLines, 0); const lastIndex = loc.last_line + contextLines; const sourceLines = rawSource.split("\n").slice(firstIndex, lastIndex); const annotatedLines = sourceLines.map((line, i) => { const lineNumber = i + firstIndex + 1; const inRange = lineNumber >= loc.first_line && lineNumber <= loc.last_line; const gutter = inRange ? ">" : " "; return `${gutter} ${lineNumber} | ${line}`; }); if (loc.first_line === loc.last_line) { const padding = utils_1.repeat(loc.first_column, " "); const underline = utils_1.repeat(loc.last_column - loc.first_column, "^"); const insertIndex = loc.first_line - firstIndex; annotatedLines.splice(insertIndex, 0, ` | ${padding}${underline}`); } return annotatedLines.join("\n"); } exports.printLoc = printLoc; class CompilerError extends Error { constructor(message, loc, rawSource) { super(message); // TODO: Create an error message that encourages users to open an issue at // https://github.com/captbaritone/eel-wasm/issues is they see this, and gives // Them an easy way to attach the right context. this.sourceContext = printLoc(loc, rawSource); this.loc = loc; } } class UserError extends CompilerError { } function createUserError(message, loc, rawSource) { return new UserError(message, loc, rawSource); } exports.createUserError = createUserError; function createCompilerError(message, loc, rawSource) { return new CompilerError(message, loc, rawSource); } exports.createCompilerError = createCompilerError; //# sourceMappingURL=errorUtils.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/ieee754.js": /*!***************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/ieee754.js ***! \***************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // Copied from https://github.com/feross/ieee754/blob/master/index.js function write(buffer, value) { // Originally these four were arguments, but we only ever use it like this. const offset = 0; const isLE = true; let mLen = 52; const nBytes = 8; var e, m, c; var eLen = nBytes * 8 - mLen - 1; var eMax = (1 << eLen) - 1; var eBias = eMax >> 1; var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0; var i = isLE ? 0 : nBytes - 1; var d = isLE ? 1 : -1; var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; value = Math.abs(value); if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0; e = eMax; } else { e = Math.floor(Math.log(value) / Math.LN2); if (value * (c = Math.pow(2, -e)) < 1) { e--; c *= 2; } if (e + eBias >= 1) { value += rt / c; } else { value += rt * Math.pow(2, 1 - eBias); } if (value * c >= 2) { e++; c /= 2; } if (e + eBias >= eMax) { m = 0; e = eMax; } else if (e + eBias >= 1) { m = (value * c - 1) * Math.pow(2, mLen); e = e + eBias; } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); e = 0; } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) { } e = (e << mLen) | m; eLen += mLen; for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) { } buffer[offset + i - d] |= s * 128; } exports.write = write; //# sourceMappingURL=ieee754.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/index.js": /*!*************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/index.js ***! \*************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const parser_1 = __webpack_require__(/*! ./parser */ "./node_modules/eel-wasm/dist/src/parser.js"); exports.parse = parser_1.parse; const compiler_1 = __webpack_require__(/*! ./compiler */ "./node_modules/eel-wasm/dist/src/compiler.js"); exports.compileModule = compiler_1.compileModule; const shims_1 = __importDefault(__webpack_require__(/*! ./shims */ "./node_modules/eel-wasm/dist/src/shims.js")); exports.shims = shims_1.default; const loader_1 = __webpack_require__(/*! ./loader */ "./node_modules/eel-wasm/dist/src/loader.js"); exports.loadModule = loader_1.loadModule; //# sourceMappingURL=index.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/loader.js": /*!**************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/loader.js ***! \**************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const shims_1 = __importDefault(__webpack_require__(/*! ./shims */ "./node_modules/eel-wasm/dist/src/shims.js")); const compiler_1 = __webpack_require__(/*! ./compiler */ "./node_modules/eel-wasm/dist/src/compiler.js"); async function loadModule({ pools, functions, eelVersion = 2, }) { let compilerPools = {}; Object.entries(pools).forEach(([key, globals]) => { compilerPools[key] = new Set(Object.keys(globals)); }); const buffer = compiler_1.compileModule({ pools: compilerPools, functions, eelVersion, }); const mod = await WebAssembly.compile(buffer); var importObject = Object.assign(Object.assign({}, pools), { shims: shims_1.default }); return await WebAssembly.instantiate(mod, importObject); } exports.loadModule = loadModule; //# sourceMappingURL=loader.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/parser.js": /*!**************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/parser.js ***! \**************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const preProcessor_1 = __webpack_require__(/*! ./preProcessor */ "./node_modules/eel-wasm/dist/src/preProcessor.js"); const envParser_1 = __webpack_require__(/*! ./envParser */ "./node_modules/eel-wasm/dist/src/envParser.js"); const astUtils_1 = __webpack_require__(/*! ./astUtils */ "./node_modules/eel-wasm/dist/src/astUtils.js"); const errorUtils_1 = __webpack_require__(/*! ./errorUtils */ "./node_modules/eel-wasm/dist/src/errorUtils.js"); function mapLoc(loc, mapper) { const first = preProcessor_1.getLoc(mapper, loc.first_column); const last = preProcessor_1.getLoc(mapper, loc.last_column); return { first_column: first.column, last_column: last.column, first_line: first.line, last_line: last.line, }; } function parse(code) { const [processedCode, mapper] = preProcessor_1.preProcess(code); try { const ast = envParser_1.parse(processedCode); return astUtils_1.mapAst(ast, (node) => { if (node.loc.first_line !== 1 || node.loc.last_line != 1) { throw errorUtils_1.createCompilerError("Unexpected multiline", node.loc, code); } return Object.assign(Object.assign({}, node), { loc: mapLoc(node.loc, mapper) }); }); } catch (e) { if (e.hash == null) { throw e; } throw errorUtils_1.createUserError(`Parse Error: ${e.message.split("\n")[3]}`, mapLoc(e.hash.loc, mapper), code); } } exports.parse = parse; //# sourceMappingURL=parser.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/preProcessor.js": /*!********************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/preProcessor.js ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function getLoc(mapper, destCol) { let previousAnchor = { destCol: 1, srcCol: 1, srcLine: 1 }; // Find the last anchor with a destCol > destCol. // Reversed: Find the first anchor with a destCol <= destCol // TODO: Use binary search mapper.forEach(anchor => { if (anchor.destCol > destCol) { return; } previousAnchor = anchor; }); const remainingColumns = destCol - previousAnchor.destCol; return { column: previousAnchor.srcCol + remainingColumns, line: previousAnchor.srcLine, }; } exports.getLoc = getLoc; // Started with this function: https://github.com/WACUP/vis_milk2/blob/cc2e85aed44373d0b6b2115c0806ec035856860a/vis_milk2/state.cpp#L1532-L1557 function preProcess(src) { const mapper = []; let srcLine = 1; let dest = ""; let lineStart = 0; let inlineComment = false; let blockComment = false; let emitAnchor = false; for (let i = 0; i < src.length; i++) { const char = src[i]; if (emitAnchor) { const destCol = dest.length + 1; const srcCol = i - lineStart + 1; mapper.push({ destCol, srcCol, srcLine }); emitAnchor = false; } if (char === "\n") { inlineComment = false; srcLine++; lineStart = i + 1; emitAnchor = true; } else if (char === "\r" && src[i + 1] === "\n") { i++; inlineComment = false; srcLine++; lineStart = i + 1; emitAnchor = true; } else if (blockComment && char === "*" && src[i + 1] === "/") { // TODO: What if we are not currently in a block comment? blockComment = false; i++; emitAnchor = true; } else if ((char === "\\" && src[i + 1] === "\\") || (char === "/" && src[i + 1] === "/")) { inlineComment = true; i++; } else if (char === "/" && src[i + 1] === "*") { blockComment = true; i++; } else if (!inlineComment && !blockComment) { dest += char; } } return [dest, mapper]; } exports.preProcess = preProcess; //# sourceMappingURL=preProcessor.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/shims.js": /*!*************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/shims.js ***! \*************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const EPSILON = 0.00001; const shims = { // TODO: Reimplement some of these functions natively in Wasm? sin: Math.sin, cos: Math.cos, tan: Math.tan, asin: Math.asin, acos: Math.acos, atan: Math.atan, atan2: Math.atan2, rand: a => Math.random() * a, pow: Math.pow, log: Math.log, log10: Math.log10, exp: Math.exp, sigmoid: function (x, y) { const t = 1 + Math.exp(-x * y); return Math.abs(t) > EPSILON ? 1.0 / t : 0; }, }; exports.default = shims; //# sourceMappingURL=shims.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/utils.js": /*!*************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/utils.js ***! \*************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function arrayJoin(arr, joiner) { const newArr = []; for (let i = 0; i < arr.length; i++) { newArr.push(arr[i]); const last = i === arr.length - 1; if (!last) { newArr.push(joiner); } } return newArr; } exports.arrayJoin = arrayJoin; function flatten(arr) { return [].concat.apply([], arr); } exports.flatten = flatten; function times(n, cb) { return new Array(n).fill(null).map((_, i) => cb(i)); } exports.times = times; function repeat(n, char) { return new Array(n).fill(char).join(""); } exports.repeat = repeat; // Maintain an ordered list of indexes for namespace/key pairs. // In Wasm binary variables are referenced by their index. In our emitter we // want to emit variables indexes as we encounter their names. This data // structure lets us issue variable indexes on demmand and then iterate through // them post facto. // // `null` may be passed for the namespace argument in order to get a global // variable that exists in all namespaces. class ScopedIdMap { constructor() { this._map = new Map(); } // Get the index of a given namespace/key pair get(namespace, key) { const jointKey = namespace == null ? key : `${namespace}::${key}`; if (!this._map.has(jointKey)) { this._map.set(jointKey, this._map.size); } // @ts-ignore We know the key is here. return this._map.get(jointKey); } size() { return this._map.size; } } exports.ScopedIdMap = ScopedIdMap; function formatList(list) { if (list.length === 0) { throw new Error("Cannot format an empty list"); } if (list.length === 1) { return list[0]; } const quoted = list.map(name => `"${name}"`); const last = quoted.pop(); return quoted.join(", ") + ` and ${last}`; } exports.formatList = formatList; //# sourceMappingURL=utils.js.map /***/ }), /***/ "./node_modules/eel-wasm/dist/src/wasmFunctions.js": /*!*********************************************************!*\ !*** ./node_modules/eel-wasm/dist/src/wasmFunctions.js ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const encoding_1 = __webpack_require__(/*! ./encoding */ "./node_modules/eel-wasm/dist/src/encoding.js"); const constants_1 = __webpack_require__(/*! ./constants */ "./node_modules/eel-wasm/dist/src/constants.js"); exports.localFuncMap = { sqr: { args: [encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], binary: [...encoding_1.op.local_get(0), ...encoding_1.op.local_get(0), encoding_1.op.f64_mul], }, bor: { args: [encoding_1.VAL_TYPE.f64, encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], binary: [ ...encoding_1.op.local_get(0), ...encoding_1.IS_NOT_ZEROISH, ...encoding_1.op.local_get(1), ...encoding_1.IS_NOT_ZEROISH, encoding_1.op.i32_or, ...encoding_1.op.i32_const(0), encoding_1.op.i32_ne, encoding_1.op.f64_convert_i32_s, ], }, band: { args: [encoding_1.VAL_TYPE.f64, encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], binary: [ ...encoding_1.op.local_get(0), ...encoding_1.IS_NOT_ZEROISH, ...encoding_1.op.local_get(1), ...encoding_1.IS_NOT_ZEROISH, encoding_1.op.i32_and, ...encoding_1.op.i32_const(0), encoding_1.op.i32_ne, encoding_1.op.f64_convert_i32_s, ], }, sign: { args: [encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], binary: [ ...encoding_1.op.f64_const(0), ...encoding_1.op.local_get(0), encoding_1.op.f64_lt, ...encoding_1.op.local_get(0), ...encoding_1.op.f64_const(0), encoding_1.op.f64_lt, encoding_1.op.i32_sub, encoding_1.op.f64_convert_i32_s, ], }, mod: { args: [encoding_1.VAL_TYPE.f64, encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], localVariables: [encoding_1.VAL_TYPE.i32], // TODO: Simplify all this type coersion binary: [ ...encoding_1.op.local_get(1), encoding_1.op.i32_trunc_f64_s, ...encoding_1.op.local_tee(2), ...encoding_1.op.i32_const(0), encoding_1.op.i32_ne, ...encoding_1.op.if(encoding_1.BLOCK.f64), ...encoding_1.op.local_get(0), encoding_1.op.i32_trunc_f64_s, ...encoding_1.op.local_get(2), encoding_1.op.i32_rem_s, encoding_1.op.f64_convert_i32_s, encoding_1.op.else, ...encoding_1.op.f64_const(0), encoding_1.op.end, ], }, bitwiseOr: { args: [encoding_1.VAL_TYPE.f64, encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], binary: [ ...encoding_1.op.local_get(0), encoding_1.op.i64_trunc_s_f64, ...encoding_1.op.local_get(1), encoding_1.op.i64_trunc_s_f64, encoding_1.op.i64_or, encoding_1.op.f64_convert_i64_s, ], }, bitwiseAnd: { args: [encoding_1.VAL_TYPE.f64, encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], binary: [ ...encoding_1.op.local_get(0), encoding_1.op.i64_trunc_s_f64, ...encoding_1.op.local_get(1), encoding_1.op.i64_trunc_s_f64, encoding_1.op.i64_and, encoding_1.op.f64_convert_i64_s, ], }, div: { args: [encoding_1.VAL_TYPE.f64, encoding_1.VAL_TYPE.f64], returns: [encoding_1.VAL_TYPE.f64], localVariables: [encoding_1.VAL_TYPE.i32], binary: [ ...encoding_1.op.local_get(1), ...encoding_1.op.f64_const(0), encoding_1.op.f64_ne, ...encoding_1.op.if(encoding_1.BLOCK.f64), ...encoding_1.op.local_get(0), ...encoding_1.op.local_get(1), encoding_1.op.f64_div, encoding_1.op.else, ...encoding_1.op.f64_const(0), encoding_1.op.end, ], }, // Takes a float buffer index and converts it to an int. Values out of range // are returned as `-1`. // // NOTE: There's actually a subtle bug that exists in Milkdrop's Eel // implementation, which we reproduce here. // // Wasm's `trunc()` rounds towards zero. This means that for index `-1` we // will return zero, since: `roundTowardZero(-1 + EPSILON) == 0` // // A subsequent check handles negative indexes, so negative indexes > than // `-1` are not affected. _getBufferIndex: { args: [encoding_1.VAL_TYPE.f64 /* 0: $index */], returns: [encoding_1.VAL_TYPE.i32 /* $noramlizedIndex */], localVariables: [ encoding_1.VAL_TYPE.f64, encoding_1.VAL_TYPE.i32, ], binary: [ ...encoding_1.op.f64_const(encoding_1.EPSILON), ...encoding_1.op.local_get(0), encoding_1.op.f64_add, // STACK: [$i + EPSILON] ...encoding_1.op.local_tee(1), encoding_1.op.i32_trunc_f64_s, // TODO We could probably make this a tee and get rid of the next get if we swap the final condition ...encoding_1.op.local_set(2), // STACK: [] ...encoding_1.op.i32_const(-1), ...encoding_1.op.local_get(2), // STACK: [-1, $truncated] ...encoding_1.op.i32_const(8), encoding_1.op.i32_mul, // STACK: [-1, $truncated * 8] ...encoding_1.op.local_get(2), ...encoding_1.op.i32_const(0), // STACK: [-1, $truncated * 8, $truncated, 0] encoding_1.op.i32_lt_s, // STACK: [-1, $truncated * 8, ] ...encoding_1.op.local_get(2), ...encoding_1.op.i32_const(constants_1.BUFFER_SIZE - 1), encoding_1.op.i32_gt_s, // STACK: [-1, $truncated * 8, , ] encoding_1.op.i32_or, // STACK: [-1, $truncated * 8, ] encoding_1.op.select, ], }, }; //# sourceMappingURL=wasmFunctions.js.map /***/ }), /***/ "./node_modules/process/browser.js": /*!*****************************************!*\ !*** ./node_modules/process/browser.js ***! \*****************************************/ /*! no static exports found */ /***/ (function(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; }; /***/ }), /***/ "./node_modules/webpack/buildin/module.js": /*!***********************************!*\ !*** (webpack)/buildin/module.js ***! \***********************************/ /*! no static exports found */ /***/ (function(module, exports) { module.exports = function(module) { if (!module.webpackPolyfill) { module.deprecate = function() {}; module.paths = []; // module.parent = undefined by default if (!module.children) module.children = []; Object.defineProperty(module, "loaded", { enumerable: true, get: function() { return module.l; } }); Object.defineProperty(module, "id", { enumerable: true, get: function() { return module.i; } }); module.webpackPolyfill = 1; } return module; }; /***/ }), /***/ "./src/assemblyscript/presetFunctions.ts": /*!***********************************************!*\ !*** ./src/assemblyscript/presetFunctions.ts ***! \***********************************************/ /*! no static exports found */ /***/ (function(module, exports) { var data = "AGFzbQEAAAABPQpgAABgAXwBfGACfHwBfGACf38AYAR/f39/AGAJf39/f3x8fHx8AGADf399AGABfwF/YAJ/fwF/YAF+AX8CuBWMAQNlbnYFYWJvcnQABAhwaXhlbEVxcwtwZXJQaXhlbEVxcwAADHBpeGVsVmFyUG9vbAR3YXJwA3wBDHBpeGVsVmFyUG9vbAR6b29tA3wBDHBpeGVsVmFyUG9vbAd6b29tZXhwA3wBDHBpeGVsVmFyUG9vbAJjeAN8AQxwaXhlbFZhclBvb2wCY3kDfAEMcGl4ZWxWYXJQb29sAnN4A3wBDHBpeGVsVmFyUG9vbAJzeQN8AQxwaXhlbFZhclBvb2wCZHgDfAEMcGl4ZWxWYXJQb29sAmR5A3wBDHBpeGVsVmFyUG9vbANyb3QDfAEMcGl4ZWxWYXJQb29sA3JhZAN8AQxwaXhlbFZhclBvb2wDYW5nA3wBDHBpeGVsVmFyUG9vbAF4A3wBDHBpeGVsVmFyUG9vbAF5A3wBCHFWYXJQb29sAnExA3wBCHFWYXJQb29sAnEyA3wBCHFWYXJQb29sAnEzA3wBCHFWYXJQb29sAnE0A3wBCHFWYXJQb29sAnE1A3wBCHFWYXJQb29sAnE2A3wBCHFWYXJQb29sAnE3A3wBCHFWYXJQb29sAnE4A3wBCHFWYXJQb29sAnE5A3wBCHFWYXJQb29sA3ExMAN8AQhxVmFyUG9vbANxMTEDfAEIcVZhclBvb2wDcTEyA3wBCHFWYXJQb29sA3ExMwN8AQhxVmFyUG9vbANxMTQDfAEIcVZhclBvb2wDcTE1A3wBCHFWYXJQb29sA3ExNgN8AQhxVmFyUG9vbANxMTcDfAEIcVZhclBvb2wDcTE4A3wBCHFWYXJQb29sA3ExOQN8AQhxVmFyUG9vbANxMjADfAEIcVZhclBvb2wDcTIxA3wBCHFWYXJQb29sA3EyMgN8AQhxVmFyUG9vbANxMjMDfAEIcVZhclBvb2wDcTI0A3wBCHFWYXJQb29sA3EyNQN8AQhxVmFyUG9vbANxMjYDfAEIcVZhclBvb2wDcTI3A3wBCHFWYXJQb29sA3EyOAN8AQhxVmFyUG9vbANxMjkDfAEIcVZhclBvb2wDcTMwA3wBCHFWYXJQb29sA3EzMQN8AQhxVmFyUG9vbANxMzIDfAEIdFZhclBvb2wCdDEDfAEIdFZhclBvb2wCdDIDfAEIdFZhclBvb2wCdDMDfAEIdFZhclBvb2wCdDQDfAEIdFZhclBvb2wCdDUDfAEIdFZhclBvb2wCdDYDfAEIdFZhclBvb2wCdDcDfAEIdFZhclBvb2wCdDgDfAEKc2hhcGVQb29sMAN4XzADfAEKc2hhcGVQb29sMAN5XzADfAEKc2hhcGVQb29sMAVyYWRfMAN8AQpzaGFwZVBvb2wwBWFuZ18wA3wBCnNoYXBlUG9vbDADcl8wA3wBCnNoYXBlUG9vbDADZ18wA3wBCnNoYXBlUG9vbDADYl8wA3wBCnNoYXBlUG9vbDADYV8wA3wBCnNoYXBlUG9vbDAEcjJfMAN8AQpzaGFwZVBvb2wwBGcyXzADfAEKc2hhcGVQb29sMARiMl8wA3wBCnNoYXBlUG9vbDAEYTJfMAN8AQpzaGFwZVBvb2wwCmJvcmRlcl9yXzADfAEKc2hhcGVQb29sMApib3JkZXJfZ18wA3wBCnNoYXBlUG9vbDAKYm9yZGVyX2JfMAN8AQpzaGFwZVBvb2wwCmJvcmRlcl9hXzADfAEKc2hhcGVQb29sMA50aGlja291dGxpbmVfMAN8AQpzaGFwZVBvb2wwCnRleHR1cmVkXzADfAEKc2hhcGVQb29sMAp0ZXhfem9vbV8wA3wBCnNoYXBlUG9vbDAJdGV4X2FuZ18wA3wBCnNoYXBlUG9vbDAKYWRkaXRpdmVfMAN8AQpzaGFwZVBvb2wxA3hfMQN8AQpzaGFwZVBvb2wxA3lfMQN8AQpzaGFwZVBvb2wxBXJhZF8xA3wBCnNoYXBlUG9vbDEFYW5nXzEDfAEKc2hhcGVQb29sMQNyXzEDfAEKc2hhcGVQb29sMQNnXzEDfAEKc2hhcGVQb29sMQNiXzEDfAEKc2hhcGVQb29sMQNhXzEDfAEKc2hhcGVQb29sMQRyMl8xA3wBCnNoYXBlUG9vbDEEZzJfMQN8AQpzaGFwZVBvb2wxBGIyXzEDfAEKc2hhcGVQb29sMQRhMl8xA3wBCnNoYXBlUG9vbDEKYm9yZGVyX3JfMQN8AQpzaGFwZVBvb2wxCmJvcmRlcl9nXzEDfAEKc2hhcGVQb29sMQpib3JkZXJfYl8xA3wBCnNoYXBlUG9vbDEKYm9yZGVyX2FfMQN8AQpzaGFwZVBvb2wxDnRoaWNrb3V0bGluZV8xA3wBCnNoYXBlUG9vbDEKdGV4dHVyZWRfMQN8AQpzaGFwZVBvb2wxCnRleF96b29tXzEDfAEKc2hhcGVQb29sMQl0ZXhfYW5nXzEDfAEKc2hhcGVQb29sMQphZGRpdGl2ZV8xA3wBCnNoYXBlUG9vbDIDeF8yA3wBCnNoYXBlUG9vbDIDeV8yA3wBCnNoYXBlUG9vbDIFcmFkXzIDfAEKc2hhcGVQb29sMgVhbmdfMgN8AQpzaGFwZVBvb2wyA3JfMgN8AQpzaGFwZVBvb2wyA2dfMgN8AQpzaGFwZVBvb2wyA2JfMgN8AQpzaGFwZVBvb2wyA2FfMgN8AQpzaGFwZVBvb2wyBHIyXzIDfAEKc2hhcGVQb29sMgRnMl8yA3wBCnNoYXBlUG9vbDIEYjJfMgN8AQpzaGFwZVBvb2wyBGEyXzIDfAEKc2hhcGVQb29sMgpib3JkZXJfcl8yA3wBCnNoYXBlUG9vbDIKYm9yZGVyX2dfMgN8AQpzaGFwZVBvb2wyCmJvcmRlcl9iXzIDfAEKc2hhcGVQb29sMgpib3JkZXJfYV8yA3wBCnNoYXBlUG9vbDIOdGhpY2tvdXRsaW5lXzIDfAEKc2hhcGVQb29sMgp0ZXh0dXJlZF8yA3wBCnNoYXBlUG9vbDIKdGV4X3pvb21fMgN8AQpzaGFwZVBvb2wyCXRleF9hbmdfMgN8AQpzaGFwZVBvb2wyCmFkZGl0aXZlXzIDfAEKc2hhcGVQb29sMwN4XzMDfAEKc2hhcGVQb29sMwN5XzMDfAEKc2hhcGVQb29sMwVyYWRfMwN8AQpzaGFwZVBvb2wzBWFuZ18zA3wBCnNoYXBlUG9vbDMDcl8zA3wBCnNoYXBlUG9vbDMDZ18zA3wBCnNoYXBlUG9vbDMDYl8zA3wBCnNoYXBlUG9vbDMDYV8zA3wBCnNoYXBlUG9vbDMEcjJfMwN8AQpzaGFwZVBvb2wzBGcyXzMDfAEKc2hhcGVQb29sMwRiMl8zA3wBCnNoYXBlUG9vbDMEYTJfMwN8AQpzaGFwZVBvb2wzCmJvcmRlcl9yXzMDfAEKc2hhcGVQb29sMwpib3JkZXJfZ18zA3wBCnNoYXBlUG9vbDMKYm9yZGVyX2JfMwN8AQpzaGFwZVBvb2wzCmJvcmRlcl9hXzMDfAEKc2hhcGVQb29sMw50aGlja291dGxpbmVfMwN8AQpzaGFwZVBvb2wzCnRleHR1cmVkXzMDfAEKc2hhcGVQb29sMwp0ZXhfem9vbV8zA3wBCnNoYXBlUG9vbDMJdGV4X2FuZ18zA3wBCnNoYXBlUG9vbDMKYWRkaXRpdmVfMwN8AQMZGAgDBwkBAQICAQYFAAAAAAAAAAAAAAAAAAUDAQABBuwMigF8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt8AUQAAAAAAAAAAAt/AUEAC3wBRAAAAAAAAAAAC3wBRAAAAAAAAAAAC34BQgALB9kB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"; module.exports = () => data; /***/ }), /***/ "./src/audio/audioLevels.js": /*!**********************************!*\ !*** ./src/audio/audioLevels.js ***! \**********************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return AudioLevels; }); class AudioLevels { constructor(audio) { this.audio = audio; let sampleRate; if (this.audio.audioContext) { sampleRate = this.audio.audioContext.sampleRate; } else { sampleRate = 44100; } const bucketHz = sampleRate / this.audio.fftSize; const bassLow = Math.clamp(Math.round(20 / bucketHz) - 1, 0, this.audio.numSamps - 1); const bassHigh = Math.clamp(Math.round(320 / bucketHz) - 1, 0, this.audio.numSamps - 1); const midHigh = Math.clamp(Math.round(2800 / bucketHz) - 1, 0, this.audio.numSamps - 1); const trebHigh = Math.clamp(Math.round(11025 / bucketHz) - 1, 0, this.audio.numSamps - 1); this.starts = [bassLow, bassHigh, midHigh]; this.stops = [bassHigh, midHigh, trebHigh]; this.val = new Float32Array(3); this.imm = new Float32Array(3); this.att = new Float32Array(3); this.avg = new Float32Array(3); this.longAvg = new Float32Array(3); this.att.fill(1); this.avg.fill(1); this.longAvg.fill(1); } /* eslint-disable camelcase */ get bass() { return this.val[0]; } get bass_att() { return this.att[0]; } get mid() { return this.val[1]; } get mid_att() { return this.att[1]; } get treb() { return this.val[2]; } get treb_att() { return this.att[2]; } /* eslint-enable camelcase */ static isFiniteNumber(num) { return Number.isFinite(num) && !Number.isNaN(num); } static adjustRateToFPS(rate, baseFPS, FPS) { return rate ** (baseFPS / FPS); } updateAudioLevels(fps, frame) { if (this.audio.freqArray.length > 0) { let effectiveFPS = fps; if (!AudioLevels.isFiniteNumber(effectiveFPS) || effectiveFPS < 15) { effectiveFPS = 15; } else if (effectiveFPS > 144) { effectiveFPS = 144; } // Clear for next loop this.imm.fill(0); for (let i = 0; i < 3; i++) { for (let j = this.starts[i]; j < this.stops[i]; j++) { this.imm[i] += this.audio.freqArray[j]; } } for (let i = 0; i < 3; i++) { let rate; if (this.imm[i] > this.avg[i]) { rate = 0.2; } else { rate = 0.5; } rate = AudioLevels.adjustRateToFPS(rate, 30.0, effectiveFPS); this.avg[i] = this.avg[i] * rate + this.imm[i] * (1 - rate); if (frame < 50) { rate = 0.9; } else { rate = 0.992; } rate = AudioLevels.adjustRateToFPS(rate, 30.0, effectiveFPS); this.longAvg[i] = this.longAvg[i] * rate + this.imm[i] * (1 - rate); if (this.longAvg[i] < 0.001) { this.val[i] = 1.0; this.att[i] = 1.0; } else { this.val[i] = this.imm[i] / this.longAvg[i]; this.att[i] = this.avg[i] / this.longAvg[i]; } } } } } /***/ }), /***/ "./src/audio/audioProcessor.js": /*!*************************************!*\ !*** ./src/audio/audioProcessor.js ***! \*************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return AudioProcessor; }); /* harmony import */ var _fft__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./fft */ "./src/audio/fft.js"); class AudioProcessor { constructor(context) { this.numSamps = 512; this.fftSize = this.numSamps * 2; this.fft = new _fft__WEBPACK_IMPORTED_MODULE_0__["default"](this.fftSize, 512, true); if (context) { this.audioContext = context; this.audible = context.createDelay(); this.analyser = context.createAnalyser(); this.analyser.smoothingTimeConstant = 0.0; this.analyser.fftSize = this.fftSize; this.audible.connect(this.analyser); // Split channels this.analyserL = context.createAnalyser(); this.analyserL.smoothingTimeConstant = 0.0; this.analyserL.fftSize = this.fftSize; this.analyserR = context.createAnalyser(); this.analyserR.smoothingTimeConstant = 0.0; this.analyserR.fftSize = this.fftSize; this.splitter = context.createChannelSplitter(2); this.audible.connect(this.splitter); this.splitter.connect(this.analyserL, 0); this.splitter.connect(this.analyserR, 1); } // Initialised once as typed arrays // Used for webaudio API raw (time domain) samples. 0 -> 255 this.timeByteArray = new Uint8Array(this.fftSize); this.timeByteArrayL = new Uint8Array(this.fftSize); this.timeByteArrayR = new Uint8Array(this.fftSize); // Signed raw samples shifted to -128 -> 127 this.timeArray = new Int8Array(this.fftSize); this.timeByteArraySignedL = new Int8Array(this.fftSize); this.timeByteArraySignedR = new Int8Array(this.fftSize); // Temporary array for smoothing this.tempTimeArrayL = new Int8Array(this.fftSize); this.tempTimeArrayR = new Int8Array(this.fftSize); // Undersampled from this.fftSize to this.numSamps this.timeArrayL = new Int8Array(this.numSamps); this.timeArrayR = new Int8Array(this.numSamps); } sampleAudio() { this.analyser.getByteTimeDomainData(this.timeByteArray); this.analyserL.getByteTimeDomainData(this.timeByteArrayL); this.analyserR.getByteTimeDomainData(this.timeByteArrayR); this.processAudio(); } updateAudio(timeByteArray, timeByteArrayL, timeByteArrayR) { this.timeByteArray.set(timeByteArray); this.timeByteArrayL.set(timeByteArrayL); this.timeByteArrayR.set(timeByteArrayR); this.processAudio(); } /* eslint-disable no-bitwise */ processAudio() { for (let i = 0, j = 0, lastIdx = 0; i < this.fftSize; i++) { // Shift Unsigned to Signed about 0 this.timeArray[i] = this.timeByteArray[i] - 128; this.timeByteArraySignedL[i] = this.timeByteArrayL[i] - 128; this.timeByteArraySignedR[i] = this.timeByteArrayR[i] - 128; this.tempTimeArrayL[i] = 0.5 * (this.timeByteArraySignedL[i] + this.timeByteArraySignedL[lastIdx]); this.tempTimeArrayR[i] = 0.5 * (this.timeByteArraySignedR[i] + this.timeByteArraySignedR[lastIdx]); // Undersampled if (i % 2 === 0) { this.timeArrayL[j] = this.tempTimeArrayL[i]; this.timeArrayR[j] = this.tempTimeArrayR[i]; j += 1; } lastIdx = i; } // Use full width samples for the FFT this.freqArray = this.fft.timeToFrequencyDomain(this.timeArray); this.freqArrayL = this.fft.timeToFrequencyDomain(this.timeByteArraySignedL); this.freqArrayR = this.fft.timeToFrequencyDomain(this.timeByteArraySignedR); } connectAudio(audionode) { audionode.connect(this.audible); } disconnectAudio(audionode) { audionode.disconnect(this.audible); } /* eslint-enable no-bitwise */ } /***/ }), /***/ "./src/audio/fft.js": /*!**************************!*\ !*** ./src/audio/fft.js ***! \**************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return FFT; }); class FFT { constructor(samplesIn, samplesOut, equalize = false) { this.samplesIn = samplesIn; this.samplesOut = samplesOut; this.equalize = equalize; this.NFREQ = samplesOut * 2; if (this.equalize) { this.initEqualizeTable(); } this.initBitRevTable(); this.initCosSinTable(); } initEqualizeTable() { this.equalizeArr = new Float32Array(this.samplesOut); const invHalfNFREQ = 1.0 / this.samplesOut; for (let i = 0; i < this.samplesOut; i++) { this.equalizeArr[i] = -0.02 * Math.log((this.samplesOut - i) * invHalfNFREQ); } } /* eslint-disable no-bitwise */ initBitRevTable() { this.bitrevtable = new Uint16Array(this.NFREQ); for (let i = 0; i < this.NFREQ; i++) { this.bitrevtable[i] = i; } let j = 0; for (let i = 0; i < this.NFREQ; i++) { if (j > i) { const temp = this.bitrevtable[i]; this.bitrevtable[i] = this.bitrevtable[j]; this.bitrevtable[j] = temp; } let m = this.NFREQ >> 1; while (m >= 1 && j >= m) { j -= m; m >>= 1; } j += m; } } initCosSinTable() { let dftsize = 2; let tabsize = 0; while (dftsize <= this.NFREQ) { tabsize += 1; dftsize <<= 1; } this.cossintable = [new Float32Array(tabsize), new Float32Array(tabsize)]; dftsize = 2; let i = 0; while (dftsize <= this.NFREQ) { const theta = -2.0 * Math.PI / dftsize; this.cossintable[0][i] = Math.cos(theta); this.cossintable[1][i] = Math.sin(theta); i += 1; dftsize <<= 1; } } timeToFrequencyDomain(waveDataIn) { const real = new Float32Array(this.NFREQ); const imag = new Float32Array(this.NFREQ); for (let i = 0; i < this.NFREQ; i++) { const idx = this.bitrevtable[i]; if (idx < this.samplesIn) { real[i] = waveDataIn[idx]; } else { real[i] = 0; } imag[i] = 0; } let dftsize = 2; let t = 0; while (dftsize <= this.NFREQ) { const wpr = this.cossintable[0][t]; const wpi = this.cossintable[1][t]; let wr = 1.0; let wi = 0.0; const hdftsize = dftsize >> 1; for (let m = 0; m < hdftsize; m++) { for (let i = m; i < this.NFREQ; i += dftsize) { const j = i + hdftsize; const tempr = wr * real[j] - wi * imag[j]; const tempi = wr * imag[j] + wi * real[j]; real[j] = real[i] - tempr; imag[j] = imag[i] - tempi; real[i] += tempr; imag[i] += tempi; } const wtemp = wr; wr = wtemp * wpr - wi * wpi; wi = wi * wpr + wtemp * wpi; } dftsize <<= 1; t += 1; } const spectralDataOut = new Float32Array(this.samplesOut); if (this.equalize) { for (let i = 0; i < this.samplesOut; i++) { spectralDataOut[i] = this.equalizeArr[i] * Math.sqrt(real[i] * real[i] + imag[i] * imag[i]); } } else { for (let i = 0; i < this.samplesOut; i++) { spectralDataOut[i] = Math.sqrt(real[i] * real[i] + imag[i] * imag[i]); } } return spectralDataOut; } /* eslint-enable no-bitwise */ } /***/ }), /***/ "./src/blankPreset.js": /*!****************************!*\ !*** ./src/blankPreset.js ***! \****************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* eslint-disable */ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () { "use strict;"; var pmap = { baseVals: { gammaadj: 1.25, wave_g: 0.5, mv_x: 12.0, warpscale: 1.0, brighten: 0.0, mv_y: 9.0, wave_scale: 1.0, echo_alpha: 0.0, additivewave: 0.0, sx: 1.0, sy: 1.0, warp: 0.01, red_blue: 0.0, wave_mode: 0.0, wave_brighten: 0.0, wrap: 0.0, zoomexp: 1.0, fshader: 0.0, wave_r: 0.5, echo_zoom: 1.0, wave_smoothing: 0.75, warpanimspeed: 1.0, wave_dots: 0.0, wave_x: 0.5, wave_y: 0.5, zoom: 1.0, solarize: 0.0, modwavealphabyvolume: 0.0, dx: 0.0, cx: 0.5, dy: 0.0, darken_center: 0.0, cy: 0.5, invert: 0.0, bmotionvectorson: 0.0, rot: 0.0, modwavealphaend: 0.95, wave_mystery: -0.2, decay: 0.9, wave_a: 1.0, wave_b: 0.5, rating: 5.0, modwavealphastart: 0.75, darken: 0.0, echo_orient: 0.0, ib_r: 0.5, ib_g: 0.5, ib_b: 0.5, ib_a: 0.0, ib_size: 0.0, ob_r: 0.5, ob_g: 0.5, ob_b: 0.5, ob_a: 0.0, ob_size: 0.0, mv_dx: 0.0, mv_dy: 0.0, mv_a: 0.0, mv_r: 0.5, mv_g: 0.5, mv_b: 0.5, mv_l: 0.0 }, init_eqs: function () { var m = {}; return m; }, frame_eqs: function (m) { m.rkeys = ["warp"]; m.zoom = 1.01 + 0.02 * m.treb_att; m.warp = 0.15 + 0.25 * m.bass_att; return m; }, pixel_eqs: function (m) { m.warp = m.warp + m.rad * 0.15; return m; }, waves: [{ baseVals: { a: 1.0, enabled: 0.0, b: 1.0, g: 1.0, scaling: 1.0, samples: 512.0, additive: 0.0, usedots: 0.0, spectrum: 0.0, r: 1.0, smoothing: 0.5, thick: 0.0, sep: 0.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; }, point_eqs: "" }, { baseVals: { a: 1.0, enabled: 0.0, b: 1.0, g: 1.0, scaling: 1.0, samples: 512.0, additive: 0.0, usedots: 0.0, spectrum: 0.0, r: 1.0, smoothing: 0.5, thick: 0.0, sep: 0.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; }, point_eqs: "" }, { baseVals: { a: 1.0, enabled: 0.0, b: 1.0, g: 1.0, scaling: 1.0, samples: 512.0, additive: 0.0, usedots: 0.0, spectrum: 0.0, r: 1.0, smoothing: 0.5, thick: 0.0, sep: 0.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; }, point_eqs: "" }, { baseVals: { a: 1.0, enabled: 0.0, b: 1.0, g: 1.0, scaling: 1.0, samples: 512.0, additive: 0.0, usedots: 0.0, spectrum: 0.0, r: 1.0, smoothing: 0.5, thick: 0.0, sep: 0.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; }, point_eqs: "" }], shapes: [{ baseVals: { r2: 0.0, a: 1.0, enabled: 0.0, b: 0.0, tex_ang: 0.0, thickoutline: 0.0, g: 0.0, textured: 0.0, g2: 1.0, tex_zoom: 1.0, additive: 0.0, border_a: 0.1, border_b: 1.0, b2: 0.0, a2: 0.0, r: 1.0, border_g: 1.0, rad: 0.1, x: 0.5, y: 0.5, ang: 0.0, sides: 4.0, border_r: 1.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; } }, { baseVals: { r2: 0.0, a: 1.0, enabled: 0.0, b: 0.0, tex_ang: 0.0, thickoutline: 0.0, g: 0.0, textured: 0.0, g2: 1.0, tex_zoom: 1.0, additive: 0.0, border_a: 0.1, border_b: 1.0, b2: 0.0, a2: 0.0, r: 1.0, border_g: 1.0, rad: 0.1, x: 0.5, y: 0.5, ang: 0.0, sides: 4.0, border_r: 1.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; } }, { baseVals: { r2: 0.0, a: 1.0, enabled: 0.0, b: 0.0, tex_ang: 0.0, thickoutline: 0.0, g: 0.0, textured: 0.0, g2: 1.0, tex_zoom: 1.0, additive: 0.0, border_a: 0.1, border_b: 1.0, b2: 0.0, a2: 0.0, r: 1.0, border_g: 1.0, rad: 0.1, x: 0.5, y: 0.5, ang: 0.0, sides: 4.0, border_r: 1.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; } }, { baseVals: { r2: 0.0, a: 1.0, enabled: 0.0, b: 0.0, tex_ang: 0.0, thickoutline: 0.0, g: 0.0, textured: 0.0, g2: 1.0, tex_zoom: 1.0, additive: 0.0, border_a: 0.1, border_b: 1.0, b2: 0.0, a2: 0.0, r: 1.0, border_g: 1.0, rad: 0.1, x: 0.5, y: 0.5, ang: 0.0, sides: 4.0, border_r: 1.0 }, init_eqs: function (m) { m.rkeys = []; return m; }, frame_eqs: function (m) { return m; } }], warp: "shader_body {\nret = texture2D(sampler_main, uv).rgb;\nret -= 0.004;\n}\n", comp: "shader_body {\nret = texture2D(sampler_main, uv).rgb;\nret *= hue_shader;\n}\n" }; return pmap; }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); /* eslint-enable */ /***/ }), /***/ "./src/equations/presetEquationRunner.js": /*!***********************************************!*\ !*** ./src/equations/presetEquationRunner.js ***! \***********************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return PresetEquationRunner; }); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ "./src/utils.js"); class PresetEquationRunner { constructor(preset, globalVars, opts) { this.preset = preset; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.qs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].range(1, 33).map(x => `q${x}`); this.ts = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].range(1, 9).map(x => `t${x}`); this.regs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].range(100).map(x => { if (x < 10) { return `reg0${x}`; } return `reg${x}`; }); this.initializeEquations(globalVars); } initializeEquations(globalVars) { this.runVertEQs = this.preset.pixel_eqs !== ""; this.mdVSQInit = null; this.mdVSRegs = null; this.mdVSFrame = null; this.mdVSUserKeys = null; this.mdVSFrameMap = null; this.mdVSShapes = null; this.mdVSUserKeysShapes = null; this.mdVSFrameMapShapes = null; this.mdVSWaves = null; this.mdVSUserKeysWaves = null; this.mdVSFrameMapWaves = null; this.mdVSQAfterFrame = null; this.gmegabuf = new Array(1048576).fill(0); const mdVSBase = { frame: globalVars.frame, time: globalVars.time, fps: globalVars.fps, bass: globalVars.bass, bass_att: globalVars.bass_att, mid: globalVars.mid, mid_att: globalVars.mid_att, treb: globalVars.treb, treb_att: globalVars.treb_att, meshx: this.mesh_width, meshy: this.mesh_height, aspectx: this.invAspectx, aspecty: this.invAspecty, pixelsx: this.texsizeX, pixelsy: this.texsizeY, gmegabuf: this.gmegabuf }; this.mdVS = Object.assign({}, this.preset.baseVals, mdVSBase); this.mdVS.megabuf = new Array(1048576).fill(0); this.mdVS.rand_start = new Float32Array([Math.random(), Math.random(), Math.random(), Math.random()]); this.mdVS.rand_preset = new Float32Array([Math.random(), Math.random(), Math.random(), Math.random()]); const nonUserKeys = this.qs.concat(this.regs, Object.keys(this.mdVS)); const mdVSAfterInit = this.preset.init_eqs(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].cloneVars(this.mdVS)); // qs need to be initialized to there init values every frame this.mdVSQInit = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSAfterInit, this.qs); this.mdVSRegs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSAfterInit, this.regs); const initUserVars = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSAfterInit, Object.keys(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].omit(mdVSAfterInit, nonUserKeys))); initUserVars.megabuf = mdVSAfterInit.megabuf; initUserVars.gmegabuf = mdVSAfterInit.gmegabuf; this.mdVSFrame = this.preset.frame_eqs(Object.assign({}, this.mdVS, this.mdVSQInit, this.mdVSRegs, initUserVars)); // user vars need to be copied between frames this.mdVSUserKeys = Object.keys(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].omit(this.mdVSFrame, nonUserKeys)); // Determine vars to carry over between frames this.mdVSFrameMap = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(this.mdVSFrame, this.mdVSUserKeys); // qs for shapes this.mdVSQAfterFrame = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(this.mdVSFrame, this.qs); this.mdVSRegs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(this.mdVSFrame, this.regs); this.mdVSWaves = []; this.mdVSTWaveInits = []; this.mdVSUserKeysWaves = []; this.mdVSFrameMapWaves = []; if (this.preset.waves && this.preset.waves.length > 0) { for (let i = 0; i < this.preset.waves.length; i++) { const wave = this.preset.waves[i]; const baseVals = wave.baseVals; if (baseVals.enabled !== 0) { let mdVSWave = Object.assign({}, baseVals, mdVSBase); const nonUserWaveKeys = this.qs.concat(this.ts, this.regs, Object.keys(mdVSWave)); Object.assign(mdVSWave, this.mdVSQAfterFrame, this.mdVSRegs); mdVSWave.megabuf = new Array(1048576).fill(0); if (wave.init_eqs) { mdVSWave = wave.init_eqs(mdVSWave); this.mdVSRegs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSWave, this.regs); // base vals need to be reset Object.assign(mdVSWave, baseVals); } this.mdVSWaves.push(mdVSWave); this.mdVSTWaveInits.push(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSWave, this.ts)); this.mdVSUserKeysWaves.push(Object.keys(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].omit(mdVSWave, nonUserWaveKeys))); this.mdVSFrameMapWaves.push(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSWave, this.mdVSUserKeysWaves[i])); } else { this.mdVSWaves.push({}); this.mdVSTWaveInits.push({}); this.mdVSUserKeysWaves.push([]); this.mdVSFrameMapWaves.push({}); } } } this.mdVSShapes = []; this.mdVSTShapeInits = []; this.mdVSUserKeysShapes = []; this.mdVSFrameMapShapes = []; if (this.preset.shapes && this.preset.shapes.length > 0) { for (let i = 0; i < this.preset.shapes.length; i++) { const shape = this.preset.shapes[i]; const baseVals = shape.baseVals; if (baseVals.enabled !== 0) { let mdVSShape = Object.assign({}, baseVals, mdVSBase); const nonUserShapeKeys = this.qs.concat(this.ts, this.regs, Object.keys(mdVSShape)); Object.assign(mdVSShape, this.mdVSQAfterFrame, this.mdVSRegs); mdVSShape.megabuf = new Array(1048576).fill(0); if (shape.init_eqs) { mdVSShape = shape.init_eqs(mdVSShape); this.mdVSRegs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSShape, this.regs); // base vals need to be reset Object.assign(mdVSShape, baseVals); } this.mdVSShapes.push(mdVSShape); this.mdVSTShapeInits.push(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSShape, this.ts)); this.mdVSUserKeysShapes.push(Object.keys(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].omit(mdVSShape, nonUserShapeKeys))); this.mdVSFrameMapShapes.push(_utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSShape, this.mdVSUserKeysShapes[i])); } else { this.mdVSShapes.push({}); this.mdVSTShapeInits.push({}); this.mdVSUserKeysShapes.push([]); this.mdVSFrameMapShapes.push({}); } } } } updatePreset(preset, globalVars) { this.preset = preset; this.initializeEquations(globalVars); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; } runFrameEquations(globalVars) { this.mdVSFrame = Object.assign({}, this.mdVS, this.mdVSQInit, this.mdVSFrameMap, globalVars); this.mdVSFrame = this.preset.frame_eqs(this.mdVSFrame); this.mdVSFrameMap = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(this.mdVSFrame, this.mdVSUserKeys); this.mdVSQAfterFrame = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(this.mdVSFrame, this.qs); return this.mdVSFrame; } runPixelEquations(mdVSVertex) { return this.preset.pixel_eqs(mdVSVertex); } runShapeFrameEquations(shapeIdx, mdVSShape) { return this.preset.shapes[shapeIdx].frame_eqs(mdVSShape); } runWaveFrameEquations(waveIdx, mdVSWave) { return this.preset.waves[waveIdx].frame_eqs(mdVSWave); } runWavePointEquations(waveIdx, mdVSWaveFrame) { return this.preset.waves[waveIdx].point_eqs(mdVSWaveFrame); } } /***/ }), /***/ "./src/equations/presetEquationRunnerWASM.js": /*!***************************************************!*\ !*** ./src/equations/presetEquationRunnerWASM.js ***! \***************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return PresetEquationRunnerWASM; }); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ "./src/utils.js"); class PresetEquationRunnerWASM { constructor(preset, globalVars, opts) { this.preset = preset; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.qs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].range(1, 33).map(x => `q${x}`); this.ts = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].range(1, 9).map(x => `t${x}`); this.regs = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].range(100).map(x => { if (x < 10) { return `reg0${x}`; } return `reg${x}`; }); this.globalKeys = ["frame", "time", "fps", "bass", "bass_att", "mid", "mid_att", "treb", "treb_att", "meshx", "meshy", "aspectx", "aspecty", "pixelsx", "pixelsy"]; this.frameKeys = ["decay", "wave_a", "wave_r", "wave_g", "wave_b", "wave_x", "wave_y", "wave_scale", "wave_smoothing", "wave_mode", "old_wave_mode", "wave_mystery", "ob_size", "ob_r", "ob_g", "ob_b", "ob_a", "ib_size", "ib_r", "ib_g", "ib_b", "ib_a", "mv_x", "mv_y", "mv_dx", "mv_dy", "mv_l", "mv_r", "mv_g", "mv_b", "mv_a", "echo_zoom", "echo_alpha", "echo_orient", "wave_dots", "wave_thick", "additivewave", "wave_brighten", "modwavealphabyvolume", "modwavealphastart", "modwavealphaend", "darken_center", "gammaadj", "warp", "warpanimspeed", "warpscale", "zoom", "zoomexp", "rot", "cx", "cy", "dx", "dy", "sx", "sy", "fshader", "wrap", "invert", "brighten", "darken", "solarize", "bmotionvectorson", "b1n", "b2n", "b3n", "b1x", "b2x", "b3x", "b1ed"]; this.waveFrameKeys = ["samples", "sep", "scaling", "spectrum", "smoothing", "r", "g", "b", "a"]; this.waveFrameInputKeys = ["samples", "r", "g", "b", "a"]; this.initializeEquations(globalVars); } getQVars(pool) { return _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pickWasm(this.preset.globalPools[pool], this.qs); } getTVars(pool) { return _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pickWasm(this.preset.globalPools[pool], this.ts); } initializeEquations(globalVars) { this.runVertEQs = !!this.preset.pixel_eqs; this.mdVSQInit = null; this.mdVSQAfterFrame = null; const mdVSBase = { frame: globalVars.frame, time: globalVars.time, fps: globalVars.fps, bass: globalVars.bass, bass_att: globalVars.bass_att, mid: globalVars.mid, mid_att: globalVars.mid_att, treb: globalVars.treb, treb_att: globalVars.treb_att, meshx: this.mesh_width, meshy: this.mesh_height, aspectx: this.invAspectx, aspecty: this.invAspecty, pixelsx: this.texsizeX, pixelsy: this.texsizeY }; this.mdVS = Object.assign({}, this.preset.baseVals, mdVSBase); // eslint-disable-next-line max-len _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools.perFrame, this.mdVS, Object.keys(this.mdVS)); this.rand_start = new Float32Array([Math.random(), Math.random(), Math.random(), Math.random()]); this.rand_preset = new Float32Array([Math.random(), Math.random(), Math.random(), Math.random()]); this.preset.init_eqs(); // qs need to be initialized to there init values every frame this.mdVSQInit = this.getQVars("perFrame"); this.preset.frame_eqs(); this.mdVSQAfterFrame = this.getQVars("perFrame"); this.mdVSTWaveInits = []; if (this.preset.waves && this.preset.waves.length > 0) { for (let i = 0; i < this.preset.waves.length; i++) { const wave = this.preset.waves[i]; const baseVals = wave.baseVals; if (baseVals.enabled !== 0) { // eslint-disable-next-line max-len _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`wavePerFrame${i}`], baseVals, Object.keys(baseVals)); if (wave.init_eqs) { wave.init_eqs(); // base vals need to be reset // eslint-disable-next-line max-len _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`wavePerFrame${i}`], baseVals, Object.keys(baseVals)); } this.mdVSTWaveInits.push(this.getTVars(`wavePerFrame${i}`)); } else { this.mdVSTWaveInits.push({}); } } } this.mdVSTShapeInits = []; if (this.preset.shapes && this.preset.shapes.length > 0) { for (let i = 0; i < this.preset.shapes.length; i++) { const shape = this.preset.shapes[i]; const baseVals = shape.baseVals; if (baseVals.enabled !== 0) { // eslint-disable-next-line max-len _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`shapePerFrame${i}`], baseVals, Object.keys(baseVals)); if (shape.init_eqs) { shape.init_eqs(); // base vals need to be reset // eslint-disable-next-line max-len _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`shapePerFrame${i}`], baseVals, Object.keys(baseVals)); } this.mdVSTShapeInits.push(this.getTVars(`shapePerFrame${i}`)); } else { this.mdVSTShapeInits.push({}); } } } } updatePreset(preset, globalVars) { this.preset = preset; this.initializeEquations(globalVars); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; } runFrameEquations(globalVars) { _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools.perFrame, this.mdVS, this.frameKeys); _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools.perFrame, this.mdVSQInit, this.qs); _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools.perFrame, globalVars, this.globalKeys); this.preset.frame_eqs(); this.preset.save_qs(); this.mdVSQAfterFrame = this.getQVars("perFrame"); // eslint-disable-next-line max-len const mdVSFrame = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pickWasm(this.preset.globalPools.perFrame, [...this.frameKeys, ...this.globalKeys]); mdVSFrame.rand_preset = this.rand_preset; mdVSFrame.rand_start = this.rand_start; return mdVSFrame; } /* eslint-disable max-len */ runWaveFrameEquations(waveIdx, globalVars) { const baseVals = this.preset.waves[waveIdx].baseVals; _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`wavePerFrame${waveIdx}`], baseVals, this.waveFrameInputKeys); _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`wavePerFrame${waveIdx}`], this.mdVSQAfterFrame, this.qs); _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`wavePerFrame${waveIdx}`], this.mdVSTWaveInits[waveIdx], this.ts); _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(this.preset.globalPools[`wavePerFrame${waveIdx}`], globalVars, this.globalKeys); this.preset.waves[waveIdx].frame_eqs(); return _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pickWasm(this.preset.globalPools[`wavePerFrame${waveIdx}`], this.waveFrameKeys); } /* eslint-enable max-len */ } /***/ }), /***/ "./src/image/imageTextures.js": /*!************************************!*\ !*** ./src/image/imageTextures.js ***! \************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ImageTextures; }); class ImageTextures { constructor(gl) { this.gl = gl; this.anisoExt = this.gl.getExtension("EXT_texture_filter_anisotropic") || this.gl.getExtension("MOZ_EXT_texture_filter_anisotropic") || this.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); this.samplers = {}; /* eslint-disable max-len */ this.clouds2Image = new Image(); this.clouds2Image.onload = () => { this.samplers.clouds2 = this.gl.createTexture(); this.bindTexture(this.samplers.clouds2, this.clouds2Image, 128, 128); }; this.clouds2Image.src = "data:image/jpeg;base64,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"; this.emptyImage = new Image(); this.emptyImage.onload = () => { this.samplers.empty = this.gl.createTexture(); this.bindTexture(this.samplers.empty, this.emptyImage, 1, 1); }; this.emptyImage.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="; /* eslint-enable max-len */ } bindTexture(texture, data, width, height) { this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1); this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, width, height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, data); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); if (this.anisoExt) { const max = this.gl.getParameter(this.anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT); this.gl.texParameterf(this.gl.TEXTURE_2D, this.anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, max); } } loadExtraImages(imageData) { Object.keys(imageData).forEach(imageName => { const { data, width, height } = imageData[imageName]; if (!this.samplers[imageName]) { const image = new Image(); image.onload = () => { this.samplers[imageName] = this.gl.createTexture(); this.bindTexture(this.samplers[imageName], image, width, height); }; image.src = data; } }); } getTexture(sampler) { const tex = this.samplers[sampler]; if (tex) { return tex; } return this.samplers.clouds2; } } /***/ }), /***/ "./src/index.js": /*!**********************!*\ !*** ./src/index.js ***! \**********************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Butterchurn; }); /* harmony import */ var ecma_proposal_math_extensions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ecma-proposal-math-extensions */ "./node_modules/ecma-proposal-math-extensions/reference-implementation/index.js"); /* harmony import */ var ecma_proposal_math_extensions__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ecma_proposal_math_extensions__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _presetBase__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./presetBase */ "./src/presetBase.js"); /* harmony import */ var _presetBase__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_presetBase__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _visualizer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./visualizer */ "./src/visualizer.js"); class Butterchurn { static createVisualizer(context, canvas, opts) { return new _visualizer__WEBPACK_IMPORTED_MODULE_2__["default"](context, canvas, opts); } } /***/ }), /***/ "./src/noise/noise.js": /*!****************************!*\ !*** ./src/noise/noise.js ***! \****************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Noise; }); class Noise { constructor(gl) { this.gl = gl; this.anisoExt = this.gl.getExtension("EXT_texture_filter_anisotropic") || this.gl.getExtension("MOZ_EXT_texture_filter_anisotropic") || this.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); this.noiseTexLQ = this.gl.createTexture(); this.noiseTexLQLite = this.gl.createTexture(); this.noiseTexMQ = this.gl.createTexture(); this.noiseTexHQ = this.gl.createTexture(); this.noiseTexVolLQ = this.gl.createTexture(); this.noiseTexVolHQ = this.gl.createTexture(); this.nTexArrLQ = Noise.createNoiseTex(256, 1); this.nTexArrLQLite = Noise.createNoiseTex(32, 1); this.nTexArrMQ = Noise.createNoiseTex(256, 4); this.nTexArrHQ = Noise.createNoiseTex(256, 8); this.nTexArrVolLQ = Noise.createNoiseVolTex(32, 1); this.nTexArrVolHQ = Noise.createNoiseVolTex(32, 4); this.bindTexture(this.noiseTexLQ, this.nTexArrLQ, 256, 256); this.bindTexture(this.noiseTexLQLite, this.nTexArrLQLite, 32, 32); this.bindTexture(this.noiseTexMQ, this.nTexArrMQ, 256, 256); this.bindTexture(this.noiseTexHQ, this.nTexArrHQ, 256, 256); this.bindTexture3D(this.noiseTexVolLQ, this.nTexArrVolLQ, 32, 32, 32); this.bindTexture3D(this.noiseTexVolHQ, this.nTexArrVolHQ, 32, 32, 32); this.noiseTexPointLQ = this.gl.createSampler(); gl.samplerParameteri(this.noiseTexPointLQ, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); gl.samplerParameteri(this.noiseTexPointLQ, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.samplerParameteri(this.noiseTexPointLQ, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.noiseTexPointLQ, gl.TEXTURE_WRAP_T, gl.REPEAT); } bindTexture(texture, data, width, height) { this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1); this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, width, height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, data); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); if (this.anisoExt) { const max = this.gl.getParameter(this.anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT); this.gl.texParameterf(this.gl.TEXTURE_2D, this.anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, max); } } bindTexture3D(texture, data, width, height, depth) { this.gl.bindTexture(this.gl.TEXTURE_3D, texture); this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1); this.gl.texImage3D(this.gl.TEXTURE_3D, 0, this.gl.RGBA, width, height, depth, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, data); this.gl.generateMipmap(this.gl.TEXTURE_3D); this.gl.texParameteri(this.gl.TEXTURE_3D, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT); this.gl.texParameteri(this.gl.TEXTURE_3D, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT); this.gl.texParameteri(this.gl.TEXTURE_3D, this.gl.TEXTURE_WRAP_R, this.gl.REPEAT); this.gl.texParameteri(this.gl.TEXTURE_3D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR); this.gl.texParameteri(this.gl.TEXTURE_3D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); if (this.anisoExt) { const max = this.gl.getParameter(this.anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT); this.gl.texParameterf(this.gl.TEXTURE_3D, this.anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, max); } } static fCubicInterpolate(y0, y1, y2, y3, t) { const t2 = t * t; const t3 = t * t2; const a0 = y3 - y2 - y0 + y1; const a1 = y0 - y1 - a0; const a2 = y2 - y0; const a3 = y1; return a0 * t3 + a1 * t2 + a2 * t + a3; } static dwCubicInterpolate(y0, y1, y2, y3, t) { const ret = []; for (let i = 0; i < 4; i++) { let f = Noise.fCubicInterpolate(y0[i] / 255.0, y1[i] / 255.0, y2[i] / 255.0, y3[i] / 255.0, t); f = Math.clamp(f, 0, 1); ret[i] = f * 255; } return ret; } static createNoiseVolTex(noiseSize, zoom) { const nsize = noiseSize * noiseSize * noiseSize; const texArr = new Uint8Array(nsize * 4); const texRange = zoom > 1 ? 216 : 256; const halfTexRange = texRange * 0.5; for (let i = 0; i < nsize; i++) { texArr[i * 4 + 0] = Math.floor(Math.random() * texRange + halfTexRange); texArr[i * 4 + 1] = Math.floor(Math.random() * texRange + halfTexRange); texArr[i * 4 + 2] = Math.floor(Math.random() * texRange + halfTexRange); texArr[i * 4 + 3] = Math.floor(Math.random() * texRange + halfTexRange); } const wordsPerSlice = noiseSize * noiseSize; const wordsPerLine = noiseSize; if (zoom > 1) { for (let z = 0; z < noiseSize; z += zoom) { for (let y = 0; y < noiseSize; y += zoom) { for (let x = 0; x < noiseSize; x++) { if (x % zoom !== 0) { const baseX = Math.floor(x / zoom) * zoom + noiseSize; const baseY = z * wordsPerSlice + y * wordsPerLine; const y0 = []; const y1 = []; const y2 = []; const y3 = []; for (let i = 0; i < 4; i++) { y0[i] = texArr[baseY * 4 + (baseX - zoom) % noiseSize * 4 + i]; y1[i] = texArr[baseY * 4 + baseX % noiseSize * 4 + i]; y2[i] = texArr[baseY * 4 + (baseX + zoom) % noiseSize * 4 + i]; y3[i] = texArr[baseY * 4 + (baseX + zoom * 2) % noiseSize * 4 + i]; } const t = x % zoom / zoom; const result = Noise.dwCubicInterpolate(y0, y1, y2, y3, t); for (let i = 0; i < 4; i++) { const offset = x * 4 + i; texArr[z * wordsPerSlice * 4 + y * wordsPerLine * 4 + offset] = result[i]; } } } } } for (let z = 0; z < noiseSize; z += zoom) { for (let x = 0; x < noiseSize; x++) { for (let y = 0; y < noiseSize; y++) { if (y % zoom !== 0) { const baseY = Math.floor(y / zoom) * zoom + noiseSize; const baseZ = z * wordsPerSlice; const y0 = []; const y1 = []; const y2 = []; const y3 = []; for (let i = 0; i < 4; i++) { const offset = x * 4 + baseZ * 4 + i; y0[i] = texArr[(baseY - zoom) % noiseSize * wordsPerLine * 4 + offset]; y1[i] = texArr[baseY % noiseSize * wordsPerLine * 4 + offset]; y2[i] = texArr[(baseY + zoom) % noiseSize * wordsPerLine * 4 + offset]; y3[i] = texArr[(baseY + zoom * 2) % noiseSize * wordsPerLine * 4 + offset]; } const t = y % zoom / zoom; const result = Noise.dwCubicInterpolate(y0, y1, y2, y3, t); for (let i = 0; i < 4; i++) { const offset = x * 4 + baseZ * 4 + i; texArr[y * wordsPerLine * 4 + offset] = result[i]; } } } } } for (let x = 0; x < noiseSize; x++) { for (let y = 0; y < noiseSize; y++) { for (let z = 0; z < noiseSize; z++) { if (z % zoom !== 0) { const baseY = y * wordsPerLine; const baseZ = Math.floor(z / zoom) * zoom + noiseSize; const y0 = []; const y1 = []; const y2 = []; const y3 = []; for (let i = 0; i < 4; i++) { const offset = x * 4 + baseY * 4 + i; y0[i] = texArr[(baseZ - zoom) % noiseSize * wordsPerSlice * 4 + offset]; y1[i] = texArr[baseZ % noiseSize * wordsPerSlice * 4 + offset]; y2[i] = texArr[(baseZ + zoom) % noiseSize * wordsPerSlice * 4 + offset]; y3[i] = texArr[(baseZ + zoom * 2) % noiseSize * wordsPerSlice * 4 + offset]; } const t = y % zoom / zoom; const result = Noise.dwCubicInterpolate(y0, y1, y2, y3, t); for (let i = 0; i < 4; i++) { const offset = x * 4 + baseY * 4 + i; texArr[z * wordsPerSlice * 4 + offset] = result[i]; } } } } } } return texArr; } static createNoiseTex(noiseSize, zoom) { const nsize = noiseSize * noiseSize; const texArr = new Uint8Array(nsize * 4); const texRange = zoom > 1 ? 216 : 256; const halfTexRange = texRange * 0.5; for (let i = 0; i < nsize; i++) { texArr[i * 4 + 0] = Math.floor(Math.random() * texRange + halfTexRange); texArr[i * 4 + 1] = Math.floor(Math.random() * texRange + halfTexRange); texArr[i * 4 + 2] = Math.floor(Math.random() * texRange + halfTexRange); texArr[i * 4 + 3] = Math.floor(Math.random() * texRange + halfTexRange); } if (zoom > 1) { for (let y = 0; y < noiseSize; y += zoom) { for (let x = 0; x < noiseSize; x++) { if (x % zoom !== 0) { const baseX = Math.floor(x / zoom) * zoom + noiseSize; const baseY = y * noiseSize; const y0 = []; const y1 = []; const y2 = []; const y3 = []; for (let z = 0; z < 4; z++) { y0[z] = texArr[baseY * 4 + (baseX - zoom) % noiseSize * 4 + z]; y1[z] = texArr[baseY * 4 + baseX % noiseSize * 4 + z]; y2[z] = texArr[baseY * 4 + (baseX + zoom) % noiseSize * 4 + z]; y3[z] = texArr[baseY * 4 + (baseX + zoom * 2) % noiseSize * 4 + z]; } const t = x % zoom / zoom; const result = Noise.dwCubicInterpolate(y0, y1, y2, y3, t); for (let z = 0; z < 4; z++) { texArr[y * noiseSize * 4 + x * 4 + z] = result[z]; } } } } for (let x = 0; x < noiseSize; x++) { for (let y = 0; y < noiseSize; y++) { if (y % zoom !== 0) { const baseY = Math.floor(y / zoom) * zoom + noiseSize; const y0 = []; const y1 = []; const y2 = []; const y3 = []; for (let z = 0; z < 4; z++) { y0[z] = texArr[(baseY - zoom) % noiseSize * noiseSize * 4 + x * 4 + z]; y1[z] = texArr[baseY % noiseSize * noiseSize * 4 + x * 4 + z]; y2[z] = texArr[(baseY + zoom) % noiseSize * noiseSize * 4 + x * 4 + z]; y3[z] = texArr[(baseY + zoom * 2) % noiseSize * noiseSize * 4 + x * 4 + z]; } const t = y % zoom / zoom; const result = Noise.dwCubicInterpolate(y0, y1, y2, y3, t); for (let z = 0; z < 4; z++) { texArr[y * noiseSize * 4 + x * 4 + z] = result[z]; } } } } } return texArr; } } /***/ }), /***/ "./src/presetBase.js": /*!***************************!*\ !*** ./src/presetBase.js ***! \***************************/ /*! no static exports found */ /***/ (function(module, exports) { /* eslint-disable */ var EPSILON = 0.00001; window.sqr = function sqr(x) { return x * x; }; window.sqrt = function sqrt(x) { return Math.sqrt(Math.abs(x)); }; window.log10 = function log10(val) { return Math.log(val) * Math.LOG10E; }; window.sign = function sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; window.rand = function rand(x) { var xf = Math.floor(x); if (xf < 1) { return Math.random(); } return Math.random() * xf; }; window.randint = function randint(x) { return Math.floor(rand(x)); }; window.bnot = function bnot(x) { return Math.abs(x) < EPSILON ? 1 : 0; }; function isFiniteNumber(num) { return isFinite(num) && !isNaN(num); } window.pow = function pow(x, y) { var z = Math.pow(x, y); if (!isFiniteNumber(z)) { // mostly from complex results return 0; } return z; }; window.div = function div(x, y) { if (y === 0) { return 0; } return x / y; }; window.mod = function mod(x, y) { if (y === 0) { return 0; } var z = Math.floor(x) % Math.floor(y); return z; }; window.bitor = function bitor(x, y) { var z = Math.floor(x) | Math.floor(y); return z; }; window.bitand = function bitand(x, y) { var z = Math.floor(x) & Math.floor(y); return z; }; window.sigmoid = function sigmoid(x, y) { var t = 1 + Math.exp(-x * y); return Math.abs(t) > EPSILON ? 1.0 / t : 0; }; window.bor = function bor(x, y) { return Math.abs(x) > EPSILON || Math.abs(y) > EPSILON ? 1 : 0; }; window.band = function band(x, y) { return Math.abs(x) > EPSILON && Math.abs(y) > EPSILON ? 1 : 0; }; window.equal = function equal(x, y) { return Math.abs(x - y) < EPSILON ? 1 : 0; }; window.above = function above(x, y) { return x > y ? 1 : 0; }; window.below = function below(x, y) { return x < y ? 1 : 0; }; window.ifcond = function ifcond(x, y, z) { return Math.abs(x) > EPSILON ? y : z; }; window.memcpy = function memcpy(megabuf, dst, src, len) { let destOffset = dst; let srcOffset = src; let copyLen = len; if (srcOffset < 0) { copyLen += srcOffset; destOffset -= srcOffset; srcOffset = 0; } if (destOffset < 0) { copyLen += destOffset; srcOffset -= destOffset; destOffset = 0; } if (copyLen > 0) { megabuf.copyWithin(destOffset, srcOffset, copyLen); } return dst; }; /* eslint-enable */ /***/ }), /***/ "./src/rendering/blendPattern.js": /*!***************************************!*\ !*** ./src/rendering/blendPattern.js ***! \***************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return BlendPattern; }); class BlendPattern { constructor(opts) { this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.vertInfoA = new Float32Array((this.mesh_width + 1) * (this.mesh_height + 1)); this.vertInfoC = new Float32Array((this.mesh_width + 1) * (this.mesh_height + 1)); this.createBlendPattern(); } static resizeMatrixValues(oldMat, oldWidth, oldHeight, newWidth, newHeight) { const newMat = new Float32Array((newWidth + 1) * (newHeight + 1)); let nVert = 0; for (let j = 0; j < newHeight + 1; j++) { for (let i = 0; i < newWidth + 1; i++) { let x = i / newHeight; let y = j / newWidth; x *= oldWidth + 1; y *= oldHeight + 1; x = Math.clamp(x, 0, oldWidth - 1); y = Math.clamp(y, 0, oldHeight - 1); const nx = Math.floor(x); const ny = Math.floor(y); const dx = x - nx; const dy = y - ny; const val00 = oldMat[ny * (oldWidth + 1) + nx]; const val01 = oldMat[ny * (oldWidth + 1) + (nx + 1)]; const val10 = oldMat[(ny + 1) * (oldWidth + 1) + nx]; const val11 = oldMat[(ny + 1) * (oldWidth + 1) + (nx + 1)]; newMat[nVert] = val00 * (1 - dx) * (1 - dy) + val01 * dx * (1 - dy) + val10 * (1 - dx) * dy + val11 * dx * dy; nVert += 1; } } return newMat; } updateGlobals(opts) { const oldMeshWidth = this.mesh_width; const oldMeshHeight = this.mesh_height; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; if (this.mesh_width !== oldMeshWidth || this.mesh_height !== oldMeshHeight) { this.vertInfoA = BlendPattern.resizeMatrixValues(this.vertInfoA, oldMeshWidth, oldMeshHeight, this.mesh_width, this.mesh_height); this.vertInfoC = BlendPattern.resizeMatrixValues(this.vertInfoC, oldMeshWidth, oldMeshHeight, this.mesh_width, this.mesh_height); } } genPlasma(x0, x1, y0, y1, dt) { const midx = Math.floor((x0 + x1) / 2); const midy = Math.floor((y0 + y1) / 2); let t00 = this.vertInfoC[y0 * (this.mesh_width + 1) + x0]; let t01 = this.vertInfoC[y0 * (this.mesh_width + 1) + x1]; let t10 = this.vertInfoC[y1 * (this.mesh_width + 1) + x0]; let t11 = this.vertInfoC[y1 * (this.mesh_width + 1) + x1]; if (y1 - y0 >= 2) { if (x0 === 0) { this.vertInfoC[midy * (this.mesh_width + 1) + x0] = 0.5 * (t00 + t10) + (Math.random() * 2 - 1) * dt * this.aspecty; } this.vertInfoC[midy * (this.mesh_width + 1) + x1] = 0.5 * (t01 + t11) + (Math.random() * 2 - 1) * dt * this.aspecty; } if (x1 - x0 >= 2) { if (y0 === 0) { this.vertInfoC[y0 * (this.mesh_width + 1) + midx] = 0.5 * (t00 + t01) + (Math.random() * 2 - 1) * dt * this.aspectx; } this.vertInfoC[y1 * (this.mesh_width + 1) + midx] = 0.5 * (t10 + t11) + (Math.random() * 2 - 1) * dt * this.aspectx; } if (y1 - y0 >= 2 && x1 - x0 >= 2) { t00 = this.vertInfoC[midy * (this.mesh_width + 1) + x0]; t01 = this.vertInfoC[midy * (this.mesh_width + 1) + x1]; t10 = this.vertInfoC[y0 * (this.mesh_width + 1) + midx]; t11 = this.vertInfoC[y1 * (this.mesh_width + 1) + midx]; this.vertInfoC[midy * (this.mesh_width + 1) + midx] = 0.25 * (t10 + t11 + t00 + t01) + (Math.random() * 2 - 1) * dt; this.genPlasma(x0, midx, y0, midy, dt * 0.5); this.genPlasma(midx, x1, y0, midy, dt * 0.5); this.genPlasma(x0, midx, midy, y1, dt * 0.5); this.genPlasma(midx, x1, midy, y1, dt * 0.5); } } createBlendPattern() { const mixType = 1 + Math.floor(Math.random() * 3); if (mixType === 0) { // not currently used let nVert = 0; for (let y = 0; y <= this.mesh_height; y++) { for (let x = 0; x <= this.mesh_width; x++) { this.vertInfoA[nVert] = 1; this.vertInfoC[nVert] = 0; nVert += 1; } } } else if (mixType === 1) { const ang = Math.random() * 6.28; const vx = Math.cos(ang); const vy = Math.sin(ang); const band = 0.1 + 0.2 * Math.random(); const invBand = 1.0 / band; let nVert = 0; for (let y = 0; y <= this.mesh_height; y++) { const fy = y / this.mesh_height * this.aspecty; for (let x = 0; x <= this.mesh_width; x++) { const fx = x / this.mesh_width * this.aspectx; let t = (fx - 0.5) * vx + (fy - 0.5) * vy + 0.5; t = (t - 0.5) / Math.sqrt(2) + 0.5; this.vertInfoA[nVert] = invBand * (1 + band); this.vertInfoC[nVert] = -invBand + invBand * t; nVert += 1; } } } else if (mixType === 2) { const band = 0.12 + 0.13 * Math.random(); const invBand = 1.0 / band; this.vertInfoC[0] = Math.random(); this.vertInfoC[this.mesh_width] = Math.random(); this.vertInfoC[this.mesh_height * (this.mesh_width + 1)] = Math.random(); this.vertInfoC[this.mesh_height * (this.mesh_width + 1) + this.mesh_width] = Math.random(); this.genPlasma(0, this.mesh_width, 0, this.mesh_height, 0.25); let minc = this.vertInfoC[0]; let maxc = this.vertInfoC[0]; let nVert = 0; for (let y = 0; y <= this.mesh_height; y++) { for (let x = 0; x <= this.mesh_width; x++) { if (minc > this.vertInfoC[nVert]) { minc = this.vertInfoC[nVert]; } if (maxc < this.vertInfoC[nVert]) { maxc = this.vertInfoC[nVert]; } nVert += 1; } } const mult = 1.0 / (maxc - minc); nVert = 0; for (let y = 0; y <= this.mesh_height; y++) { for (let x = 0; x <= this.mesh_width; x++) { const t = (this.vertInfoC[nVert] - minc) * mult; this.vertInfoA[nVert] = invBand * (1 + band); this.vertInfoC[nVert] = -invBand + invBand * t; nVert += 1; } } } else if (mixType === 3) { const band = 0.02 + 0.14 * Math.random() + 0.34 * Math.random(); const invBand = 1.0 / band; const dir = Math.floor(Math.random() * 2) * 2 - 1; let nVert = 0; for (let y = 0; y <= this.mesh_height; y++) { const dy = (y / this.mesh_height - 0.5) * this.aspecty; for (let x = 0; x <= this.mesh_width; x++) { const dx = (x / this.mesh_width - 0.5) * this.aspectx; let t = Math.sqrt(dx * dx + dy * dy) * 1.41421; if (dir === -1) { t = 1 - t; } this.vertInfoA[nVert] = invBand * (1 + band); this.vertInfoC[nVert] = -invBand + invBand * t; nVert += 1; } } } } } /***/ }), /***/ "./src/rendering/motionVectors/motionVectors.js": /*!******************************************************!*\ !*** ./src/rendering/motionVectors/motionVectors.js ***! \******************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return MotionVectors; }); /* harmony import */ var _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shaders/shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class MotionVectors { constructor(gl, opts) { this.gl = gl; this.maxX = 64; this.maxY = 48; this.positions = new Float32Array(this.maxX * this.maxY * 2 * 3); this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.positionVertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es in vec3 aPos; void main(void) { gl_Position = vec4(aPos, 1.0); } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; out vec4 fragColor; uniform vec4 u_color; void main(void) { fragColor = u_color; } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.aPosLoc = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.colorLoc = this.gl.getUniformLocation(this.shaderProgram, "u_color"); } getMotionDir(warpUVs, fx, fy) { const y0 = Math.floor(fy * this.mesh_height); const dy = fy * this.mesh_height - y0; const x0 = Math.floor(fx * this.mesh_width); const dx = fx * this.mesh_width - x0; const x1 = x0 + 1; const y1 = y0 + 1; const gridX1 = this.mesh_width + 1; let fx2; let fy2; fx2 = warpUVs[(y0 * gridX1 + x0) * 2 + 0] * (1 - dx) * (1 - dy); fy2 = warpUVs[(y0 * gridX1 + x0) * 2 + 1] * (1 - dx) * (1 - dy); fx2 += warpUVs[(y0 * gridX1 + x1) * 2 + 0] * dx * (1 - dy); fy2 += warpUVs[(y0 * gridX1 + x1) * 2 + 1] * dx * (1 - dy); fx2 += warpUVs[(y1 * gridX1 + x0) * 2 + 0] * (1 - dx) * dy; fy2 += warpUVs[(y1 * gridX1 + x0) * 2 + 1] * (1 - dx) * dy; fx2 += warpUVs[(y1 * gridX1 + x1) * 2 + 0] * dx * dy; fy2 += warpUVs[(y1 * gridX1 + x1) * 2 + 1] * dx * dy; return [fx2, 1.0 - fy2]; } generateMotionVectors(mdVSFrame, warpUVs) { const mvOn = mdVSFrame.bmotionvectorson; const mvA = mvOn === 0 ? 0 : mdVSFrame.mv_a; let nX = Math.floor(mdVSFrame.mv_x); let nY = Math.floor(mdVSFrame.mv_y); if (mvA > 0.001 && nX > 0 && nY > 0) { let dx = mdVSFrame.mv_x - nX; let dy = mdVSFrame.mv_y - nY; if (nX > this.maxX) { nX = this.maxX; dx = 0; } if (nY > this.maxY) { nY = this.maxY; dy = 0; } const dx2 = mdVSFrame.mv_dx; const dy2 = mdVSFrame.mv_dy; const lenMult = mdVSFrame.mv_l; const minLen = 1.0 / this.texsizeX; this.numVecVerts = 0; for (let j = 0; j < nY; j++) { let fy = (j + 0.25) / (nY + dy + 0.25 - 1.0); fy -= dy2; if (fy > 0.0001 && fy < 0.9999) { for (let i = 0; i < nX; i++) { let fx = (i + 0.25) / (nX + dx + 0.25 - 1.0); fx += dx2; if (fx > 0.0001 && fx < 0.9999) { const fx2arr = this.getMotionDir(warpUVs, fx, fy); let fx2 = fx2arr[0]; let fy2 = fx2arr[1]; let dxi = fx2 - fx; let dyi = fy2 - fy; dxi *= lenMult; dyi *= lenMult; let fdist = Math.sqrt(dxi * dxi + dyi * dyi); if (fdist < minLen && fdist > 0.00000001) { fdist = minLen / fdist; dxi *= fdist; dyi *= fdist; } else { dxi = minLen; dxi = minLen; } fx2 = fx + dxi; fy2 = fy + dyi; const vx1 = 2.0 * fx - 1.0; const vy1 = 2.0 * fy - 1.0; const vx2 = 2.0 * fx2 - 1.0; const vy2 = 2.0 * fy2 - 1.0; this.positions[this.numVecVerts * 3 + 0] = vx1; this.positions[this.numVecVerts * 3 + 1] = vy1; this.positions[this.numVecVerts * 3 + 2] = 0; this.positions[(this.numVecVerts + 1) * 3 + 0] = vx2; this.positions[(this.numVecVerts + 1) * 3 + 1] = vy2; this.positions[(this.numVecVerts + 1) * 3 + 2] = 0; this.numVecVerts += 2; } } } } if (this.numVecVerts > 0) { this.color = [mdVSFrame.mv_r, mdVSFrame.mv_g, mdVSFrame.mv_b, mvA]; return true; } } return false; } drawMotionVectors(mdVSFrame, warpUVs) { if (this.generateMotionVectors(mdVSFrame, warpUVs)) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aPosLoc, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLoc); this.gl.uniform4fv(this.colorLoc, this.color); this.gl.lineWidth(1); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawArrays(this.gl.LINES, 0, this.numVecVerts); } } } /***/ }), /***/ "./src/rendering/renderer.js": /*!***********************************!*\ !*** ./src/rendering/renderer.js ***! \***********************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Renderer; }); /* harmony import */ var _audio_audioLevels__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../audio/audioLevels */ "./src/audio/audioLevels.js"); /* harmony import */ var _blankPreset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../blankPreset */ "./src/blankPreset.js"); /* harmony import */ var _blankPreset__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_blankPreset__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _equations_presetEquationRunner__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../equations/presetEquationRunner */ "./src/equations/presetEquationRunner.js"); /* harmony import */ var _equations_presetEquationRunnerWASM__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../equations/presetEquationRunnerWASM */ "./src/equations/presetEquationRunnerWASM.js"); /* harmony import */ var _waves_basicWaveform__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./waves/basicWaveform */ "./src/rendering/waves/basicWaveform.js"); /* harmony import */ var _waves_customWaveform__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./waves/customWaveform */ "./src/rendering/waves/customWaveform.js"); /* harmony import */ var _shapes_customShape__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./shapes/customShape */ "./src/rendering/shapes/customShape.js"); /* harmony import */ var _sprites_border__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./sprites/border */ "./src/rendering/sprites/border.js"); /* harmony import */ var _sprites_darkenCenter__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./sprites/darkenCenter */ "./src/rendering/sprites/darkenCenter.js"); /* harmony import */ var _motionVectors_motionVectors__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./motionVectors/motionVectors */ "./src/rendering/motionVectors/motionVectors.js"); /* harmony import */ var _shaders_warp__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./shaders/warp */ "./src/rendering/shaders/warp.js"); /* harmony import */ var _shaders_comp__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./shaders/comp */ "./src/rendering/shaders/comp.js"); /* harmony import */ var _shaders_output__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./shaders/output */ "./src/rendering/shaders/output.js"); /* harmony import */ var _shaders_resample__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./shaders/resample */ "./src/rendering/shaders/resample.js"); /* harmony import */ var _shaders_blur_blur__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./shaders/blur/blur */ "./src/rendering/shaders/blur/blur.js"); /* harmony import */ var _noise_noise__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../noise/noise */ "./src/noise/noise.js"); /* harmony import */ var _image_imageTextures__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../image/imageTextures */ "./src/image/imageTextures.js"); /* harmony import */ var _text_titleText__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./text/titleText */ "./src/rendering/text/titleText.js"); /* harmony import */ var _blendPattern__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./blendPattern */ "./src/rendering/blendPattern.js"); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../utils */ "./src/utils.js"); class Renderer { constructor(gl, audio, opts) { this.gl = gl; this.audio = audio; this.frameNum = 0; this.fps = 30; this.time = 0; this.presetTime = 0; this.lastTime = performance.now(); this.timeHist = [0]; this.timeHistMax = 120; this.blending = false; this.blendStartTime = 0; this.blendProgress = 0; this.blendDuration = 0; this.width = opts.width || 1200; this.height = opts.height || 900; this.mesh_width = opts.meshWidth || 48; this.mesh_height = opts.meshHeight || 36; this.pixelRatio = opts.pixelRatio || window.devicePixelRatio || 1; this.textureRatio = opts.textureRatio || 1; this.outputFXAA = opts.outputFXAA || false; this.texsizeX = this.width * this.pixelRatio * this.textureRatio; this.texsizeY = this.height * this.pixelRatio * this.textureRatio; this.aspectx = this.texsizeY > this.texsizeX ? this.texsizeX / this.texsizeY : 1; this.aspecty = this.texsizeX > this.texsizeY ? this.texsizeY / this.texsizeX : 1; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.qs = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].range(1, 33).map(x => `q${x}`); this.ts = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].range(1, 9).map(x => `t${x}`); this.regs = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].range(0, 100).map(x => { if (x < 10) { return `reg0${x}`; } return `reg${x}`; }); this.blurRatios = [[0.5, 0.25], [0.125, 0.125], [0.0625, 0.0625]]; this.audioLevels = new _audio_audioLevels__WEBPACK_IMPORTED_MODULE_0__["default"](this.audio); this.prevFrameBuffer = this.gl.createFramebuffer(); this.targetFrameBuffer = this.gl.createFramebuffer(); this.prevTexture = this.gl.createTexture(); this.targetTexture = this.gl.createTexture(); this.compFrameBuffer = this.gl.createFramebuffer(); this.compTexture = this.gl.createTexture(); this.anisoExt = this.gl.getExtension("EXT_texture_filter_anisotropic") || this.gl.getExtension("MOZ_EXT_texture_filter_anisotropic") || this.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); this.bindFrameBufferTexture(this.prevFrameBuffer, this.prevTexture); this.bindFrameBufferTexture(this.targetFrameBuffer, this.targetTexture); this.bindFrameBufferTexture(this.compFrameBuffer, this.compTexture); const params = { pixelRatio: this.pixelRatio, textureRatio: this.textureRatio, texsizeX: this.texsizeX, texsizeY: this.texsizeY, mesh_width: this.mesh_width, mesh_height: this.mesh_height, aspectx: this.aspectx, aspecty: this.aspecty }; this.noise = new _noise_noise__WEBPACK_IMPORTED_MODULE_15__["default"](gl); this.image = new _image_imageTextures__WEBPACK_IMPORTED_MODULE_16__["default"](gl); this.warpShader = new _shaders_warp__WEBPACK_IMPORTED_MODULE_10__["default"](gl, this.noise, this.image, params); this.compShader = new _shaders_comp__WEBPACK_IMPORTED_MODULE_11__["default"](gl, this.noise, this.image, params); this.outputShader = new _shaders_output__WEBPACK_IMPORTED_MODULE_12__["default"](gl, params); this.prevWarpShader = new _shaders_warp__WEBPACK_IMPORTED_MODULE_10__["default"](gl, this.noise, this.image, params); this.prevCompShader = new _shaders_comp__WEBPACK_IMPORTED_MODULE_11__["default"](gl, this.noise, this.image, params); this.numBlurPasses = 0; this.blurShader1 = new _shaders_blur_blur__WEBPACK_IMPORTED_MODULE_14__["default"](0, this.blurRatios, gl, params); this.blurShader2 = new _shaders_blur_blur__WEBPACK_IMPORTED_MODULE_14__["default"](1, this.blurRatios, gl, params); this.blurShader3 = new _shaders_blur_blur__WEBPACK_IMPORTED_MODULE_14__["default"](2, this.blurRatios, gl, params); this.blurTexture1 = this.blurShader1.blurVerticalTexture; this.blurTexture2 = this.blurShader2.blurVerticalTexture; this.blurTexture3 = this.blurShader3.blurVerticalTexture; this.basicWaveform = new _waves_basicWaveform__WEBPACK_IMPORTED_MODULE_4__["default"](gl, params); this.customWaveforms = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].range(4).map(i => new _waves_customWaveform__WEBPACK_IMPORTED_MODULE_5__["default"](i, gl, params)); this.customShapes = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].range(4).map(i => new _shapes_customShape__WEBPACK_IMPORTED_MODULE_6__["default"](i, gl, params)); this.prevCustomWaveforms = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].range(4).map(i => new _waves_customWaveform__WEBPACK_IMPORTED_MODULE_5__["default"](i, gl, params)); this.prevCustomShapes = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].range(4).map(i => new _shapes_customShape__WEBPACK_IMPORTED_MODULE_6__["default"](i, gl, params)); this.darkenCenter = new _sprites_darkenCenter__WEBPACK_IMPORTED_MODULE_8__["default"](gl, params); this.innerBorder = new _sprites_border__WEBPACK_IMPORTED_MODULE_7__["default"](gl, params); this.outerBorder = new _sprites_border__WEBPACK_IMPORTED_MODULE_7__["default"](gl, params); this.motionVectors = new _motionVectors_motionVectors__WEBPACK_IMPORTED_MODULE_9__["default"](gl, params); this.titleText = new _text_titleText__WEBPACK_IMPORTED_MODULE_17__["default"](gl, params); this.blendPattern = new _blendPattern__WEBPACK_IMPORTED_MODULE_18__["default"](params); this.resampleShader = new _shaders_resample__WEBPACK_IMPORTED_MODULE_13__["default"](gl); this.supertext = { startTime: -1 }; this.warpUVs = new Float32Array((this.mesh_width + 1) * (this.mesh_height + 1) * 2); this.warpColor = new Float32Array((this.mesh_width + 1) * (this.mesh_height + 1) * 4); this.gl.clearColor(0, 0, 0, 1); this.blankPreset = _blankPreset__WEBPACK_IMPORTED_MODULE_1___default.a; const globalVars = { frame: 0, time: 0, fps: 45, bass: 1, bass_att: 1, mid: 1, mid_att: 1, treb: 1, treb_att: 1 }; this.preset = _blankPreset__WEBPACK_IMPORTED_MODULE_1___default.a; this.prevPreset = this.preset; this.presetEquationRunner = new _equations_presetEquationRunner__WEBPACK_IMPORTED_MODULE_2__["default"](this.preset, globalVars, params); this.prevPresetEquationRunner = new _equations_presetEquationRunner__WEBPACK_IMPORTED_MODULE_2__["default"](this.prevPreset, globalVars, params); if (!this.preset.useWASM) { this.regVars = this.presetEquationRunner.mdVSRegs; } } static getHighestBlur(t) { if (/sampler_blur3/.test(t)) { return 3; } else if (/sampler_blur2/.test(t)) { return 2; } else if (/sampler_blur1/.test(t)) { return 1; } return 0; } loadPreset(preset, blendTime) { this.blendPattern.createBlendPattern(); this.blending = true; this.blendStartTime = this.time; this.blendDuration = blendTime; this.blendProgress = 0; this.prevPresetEquationRunner = this.presetEquationRunner; this.prevPreset = this.preset; this.preset = preset; this.presetTime = this.time; const globalVars = { frame: this.frameNum, time: this.time, fps: this.fps, bass: this.audioLevels.bass, bass_att: this.audioLevels.bass_att, mid: this.audioLevels.mid, mid_att: this.audioLevels.mid_att, treb: this.audioLevels.treb, treb_att: this.audioLevels.treb_att }; const params = { pixelRatio: this.pixelRatio, textureRatio: this.textureRatio, texsizeX: this.texsizeX, texsizeY: this.texsizeY, mesh_width: this.mesh_width, mesh_height: this.mesh_height, aspectx: this.aspectx, aspecty: this.aspecty }; if (preset.useWASM) { this.preset.globalPools.perFrame.old_wave_mode.value = this.prevPreset.baseVals.wave_mode; this.preset.baseVals.old_wave_mode = this.prevPreset.baseVals.wave_mode; this.presetEquationRunner = new _equations_presetEquationRunnerWASM__WEBPACK_IMPORTED_MODULE_3__["default"](this.preset, globalVars, params); if (this.preset.pixel_eqs_initialize_array) { this.preset.pixel_eqs_initialize_array(this.mesh_width, this.mesh_height); } } else { this.preset.baseVals.old_wave_mode = this.prevPreset.baseVals.wave_mode; this.presetEquationRunner = new _equations_presetEquationRunner__WEBPACK_IMPORTED_MODULE_2__["default"](this.preset, globalVars, params); this.regVars = this.presetEquationRunner.mdVSRegs; } const tmpWarpShader = this.prevWarpShader; this.prevWarpShader = this.warpShader; this.warpShader = tmpWarpShader; const tmpCompShader = this.prevCompShader; this.prevCompShader = this.compShader; this.compShader = tmpCompShader; const warpText = this.preset.warp.trim(); const compText = this.preset.comp.trim(); this.warpShader.updateShader(warpText); this.compShader.updateShader(compText); if (warpText.length === 0) { this.numBlurPasses = 0; } else { this.numBlurPasses = Renderer.getHighestBlur(warpText); } if (compText.length !== 0) { this.numBlurPasses = Math.max(this.numBlurPasses, Renderer.getHighestBlur(compText)); } } loadExtraImages(imageData) { this.image.loadExtraImages(imageData); } setRendererSize(width, height, opts) { const oldTexsizeX = this.texsizeX; const oldTexsizeY = this.texsizeY; this.width = width; this.height = height; this.mesh_width = opts.meshWidth || this.mesh_width; this.mesh_height = opts.meshHeight || this.mesh_height; this.pixelRatio = opts.pixelRatio || this.pixelRatio; this.textureRatio = opts.textureRatio || this.textureRatio; this.texsizeX = width * this.pixelRatio * this.textureRatio; this.texsizeY = height * this.pixelRatio * this.textureRatio; this.aspectx = this.texsizeY > this.texsizeX ? this.texsizeX / this.texsizeY : 1; this.aspecty = this.texsizeX > this.texsizeY ? this.texsizeY / this.texsizeX : 1; if (this.texsizeX !== oldTexsizeX || this.texsizeY !== oldTexsizeY) { // copy target texture, because we flip prev/target at start of render const targetTextureNew = this.gl.createTexture(); this.bindFrameBufferTexture(this.targetFrameBuffer, targetTextureNew); this.bindFrambufferAndSetViewport(this.targetFrameBuffer, this.texsizeX, this.texsizeY); this.resampleShader.renderQuadTexture(this.targetTexture); this.targetTexture = targetTextureNew; this.bindFrameBufferTexture(this.prevFrameBuffer, this.prevTexture); this.bindFrameBufferTexture(this.compFrameBuffer, this.compTexture); } this.updateGlobals(); // rerender current frame at new size if (this.frameNum > 0) { this.renderToScreen(); } } setInternalMeshSize(width, height) { this.mesh_width = width; this.mesh_height = height; this.updateGlobals(); } setOutputAA(useAA) { this.outputFXAA = useAA; } updateGlobals() { const params = { pixelRatio: this.pixelRatio, textureRatio: this.textureRatio, texsizeX: this.texsizeX, texsizeY: this.texsizeY, mesh_width: this.mesh_width, mesh_height: this.mesh_height, aspectx: this.aspectx, aspecty: this.aspecty }; this.presetEquationRunner.updateGlobals(params); this.prevPresetEquationRunner.updateGlobals(params); this.warpShader.updateGlobals(params); this.prevWarpShader.updateGlobals(params); this.compShader.updateGlobals(params); this.prevCompShader.updateGlobals(params); this.outputShader.updateGlobals(params); this.blurShader1.updateGlobals(params); this.blurShader2.updateGlobals(params); this.blurShader3.updateGlobals(params); this.basicWaveform.updateGlobals(params); this.customWaveforms.forEach(wave => wave.updateGlobals(params)); this.customShapes.forEach(shape => shape.updateGlobals(params)); this.prevCustomWaveforms.forEach(wave => wave.updateGlobals(params)); this.prevCustomShapes.forEach(shape => shape.updateGlobals(params)); this.darkenCenter.updateGlobals(params); this.innerBorder.updateGlobals(params); this.outerBorder.updateGlobals(params); this.motionVectors.updateGlobals(params); this.titleText.updateGlobals(params); this.blendPattern.updateGlobals(params); this.warpUVs = new Float32Array((this.mesh_width + 1) * (this.mesh_height + 1) * 2); this.warpColor = new Float32Array((this.mesh_width + 1) * (this.mesh_height + 1) * 4); if (this.preset.pixel_eqs_initialize_array) { this.preset.pixel_eqs_initialize_array(this.mesh_width, this.mesh_height); } } calcTimeAndFPS(elapsedTime) { let elapsed; if (elapsedTime) { elapsed = elapsedTime; } else { const newTime = performance.now(); elapsed = (newTime - this.lastTime) / 1000.0; if (elapsed > 1.0 || elapsed < 0.0 || this.frame < 2) { elapsed = 1.0 / 30.0; } this.lastTime = newTime; } this.time += 1.0 / this.fps; if (this.blending) { this.blendProgress = (this.time - this.blendStartTime) / this.blendDuration; if (this.blendProgress > 1.0) { this.blending = false; } } const newHistTime = this.timeHist[this.timeHist.length - 1] + elapsed; this.timeHist.push(newHistTime); if (this.timeHist.length > this.timeHistMax) { this.timeHist.shift(); } const newFPS = this.timeHist.length / (newHistTime - this.timeHist[0]); if (Math.abs(newFPS - this.fps) > 3.0 && this.frame > this.timeHistMax) { this.fps = newFPS; } else { const damping = 0.93; this.fps = damping * this.fps + (1.0 - damping) * newFPS; } } runPixelEquations(presetEquationRunner, mdVSFrame, globalVars, blending) { const gridX = this.mesh_width; const gridZ = this.mesh_height; const gridX1 = gridX + 1; const gridZ1 = gridZ + 1; const warpTimeV = this.time * mdVSFrame.warpanimspeed; const warpScaleInv = 1.0 / mdVSFrame.warpscale; const warpf0 = 11.68 + 4.0 * Math.cos(warpTimeV * 1.413 + 10); const warpf1 = 8.77 + 3.0 * Math.cos(warpTimeV * 1.113 + 7); const warpf2 = 10.54 + 3.0 * Math.cos(warpTimeV * 1.233 + 3); const warpf3 = 11.49 + 4.0 * Math.cos(warpTimeV * 0.933 + 5); const texelOffsetX = 0.0 / this.texsizeX; const texelOffsetY = 0.0 / this.texsizeY; const aspectx = this.aspectx; const aspecty = this.aspecty; let offset = 0; let offsetColor = 0; if (!presetEquationRunner.preset.useWASM) { let mdVSVertex = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].cloneVars(mdVSFrame); let warp = mdVSVertex.warp; let zoom = mdVSVertex.zoom; let zoomExp = mdVSVertex.zoomexp; let cx = mdVSVertex.cx; let cy = mdVSVertex.cy; let sx = mdVSVertex.sx; let sy = mdVSVertex.sy; let dx = mdVSVertex.dx; let dy = mdVSVertex.dy; let rot = mdVSVertex.rot; for (let iz = 0; iz < gridZ1; iz++) { for (let ix = 0; ix < gridX1; ix++) { const x = ix / gridX * 2.0 - 1.0; const y = iz / gridZ * 2.0 - 1.0; const rad = Math.sqrt(x * x * aspectx * aspectx + y * y * aspecty * aspecty); if (presetEquationRunner.runVertEQs) { let ang; if (iz === gridZ / 2 && ix === gridX / 2) { ang = 0; } else { ang = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].atan2(y * aspecty, x * aspectx); } mdVSVertex.x = x * 0.5 * aspectx + 0.5; mdVSVertex.y = y * -0.5 * aspecty + 0.5; mdVSVertex.rad = rad; mdVSVertex.ang = ang; mdVSVertex.zoom = mdVSFrame.zoom; mdVSVertex.zoomexp = mdVSFrame.zoomexp; mdVSVertex.rot = mdVSFrame.rot; mdVSVertex.warp = mdVSFrame.warp; mdVSVertex.cx = mdVSFrame.cx; mdVSVertex.cy = mdVSFrame.cy; mdVSVertex.dx = mdVSFrame.dx; mdVSVertex.dy = mdVSFrame.dy; mdVSVertex.sx = mdVSFrame.sx; mdVSVertex.sy = mdVSFrame.sy; mdVSVertex = presetEquationRunner.runPixelEquations(mdVSVertex); warp = mdVSVertex.warp; zoom = mdVSVertex.zoom; zoomExp = mdVSVertex.zoomexp; cx = mdVSVertex.cx; cy = mdVSVertex.cy; sx = mdVSVertex.sx; sy = mdVSVertex.sy; dx = mdVSVertex.dx; dy = mdVSVertex.dy; rot = mdVSVertex.rot; } const zoom2V = zoom ** zoomExp ** (rad * 2.0 - 1.0); const zoom2Inv = 1.0 / zoom2V; let u = x * 0.5 * aspectx * zoom2Inv + 0.5; let v = -y * 0.5 * aspecty * zoom2Inv + 0.5; u = (u - cx) / sx + cx; v = (v - cy) / sy + cy; if (warp !== 0) { u += warp * 0.0035 * Math.sin(warpTimeV * 0.333 + warpScaleInv * (x * warpf0 - y * warpf3)); v += warp * 0.0035 * Math.cos(warpTimeV * 0.375 - warpScaleInv * (x * warpf2 + y * warpf1)); u += warp * 0.0035 * Math.cos(warpTimeV * 0.753 - warpScaleInv * (x * warpf1 - y * warpf2)); v += warp * 0.0035 * Math.sin(warpTimeV * 0.825 + warpScaleInv * (x * warpf0 + y * warpf3)); } const u2 = u - cx; const v2 = v - cy; const cosRot = Math.cos(rot); const sinRot = Math.sin(rot); u = u2 * cosRot - v2 * sinRot + cx; v = u2 * sinRot + v2 * cosRot + cy; u -= dx; v -= dy; u = (u - 0.5) / aspectx + 0.5; v = (v - 0.5) / aspecty + 0.5; u += texelOffsetX; v += texelOffsetY; if (!blending) { this.warpUVs[offset] = u; this.warpUVs[offset + 1] = v; this.warpColor[offsetColor + 0] = 1; this.warpColor[offsetColor + 1] = 1; this.warpColor[offsetColor + 2] = 1; this.warpColor[offsetColor + 3] = 1; } else { let mix2 = this.blendPattern.vertInfoA[offset / 2] * this.blendProgress + this.blendPattern.vertInfoC[offset / 2]; mix2 = Math.clamp(mix2, 0, 1); this.warpUVs[offset] = this.warpUVs[offset] * mix2 + u * (1 - mix2); this.warpUVs[offset + 1] = this.warpUVs[offset + 1] * mix2 + v * (1 - mix2); this.warpColor[offsetColor + 0] = 1; this.warpColor[offsetColor + 1] = 1; this.warpColor[offsetColor + 2] = 1; this.warpColor[offsetColor + 3] = mix2; } offset += 2; offsetColor += 4; } } this.mdVSVertex = mdVSVertex; } else { const varPool = presetEquationRunner.preset.globalPools.perVertex; _utils__WEBPACK_IMPORTED_MODULE_19__["default"].setWasm(varPool, globalVars, presetEquationRunner.globalKeys); _utils__WEBPACK_IMPORTED_MODULE_19__["default"].setWasm(varPool, presetEquationRunner.mdVSQAfterFrame, presetEquationRunner.qs); varPool.zoom.value = mdVSFrame.zoom; varPool.zoomexp.value = mdVSFrame.zoomexp; varPool.rot.value = mdVSFrame.rot; varPool.warp.value = mdVSFrame.warp; varPool.cx.value = mdVSFrame.cx; varPool.cy.value = mdVSFrame.cy; varPool.dx.value = mdVSFrame.dx; varPool.dy.value = mdVSFrame.dy; varPool.sx.value = mdVSFrame.sx; varPool.sy.value = mdVSFrame.sy; presetEquationRunner.preset.pixel_eqs_wasm(presetEquationRunner.runVertEQs, this.mesh_width, this.mesh_height, this.time, mdVSFrame.warpanimspeed, mdVSFrame.warpscale, this.aspectx, this.aspecty); if (!blending) { this.warpUVs = presetEquationRunner.preset.pixel_eqs_get_array(); this.warpColor.fill(1); } else { const newWarpUVs = presetEquationRunner.preset.pixel_eqs_get_array(); let offset = 0; let offsetColor = 0; for (let iz = 0; iz < gridZ1; iz++) { for (let ix = 0; ix < gridX1; ix++) { const u = newWarpUVs[offset]; const v = newWarpUVs[offset + 1]; let mix2 = this.blendPattern.vertInfoA[offset / 2] * this.blendProgress + this.blendPattern.vertInfoC[offset / 2]; mix2 = Math.clamp(mix2, 0, 1); this.warpUVs[offset] = this.warpUVs[offset] * mix2 + u * (1 - mix2); this.warpUVs[offset + 1] = this.warpUVs[offset + 1] * mix2 + v * (1 - mix2); this.warpColor[offsetColor + 0] = 1; this.warpColor[offsetColor + 1] = 1; this.warpColor[offsetColor + 2] = 1; this.warpColor[offsetColor + 3] = mix2; offset += 2; offsetColor += 4; } } } } } static mixFrameEquations(blendProgress, mdVSFrame, mdVSFramePrev) { const mix = 0.5 - 0.5 * Math.cos(blendProgress * Math.PI); const mix2 = 1 - mix; const snapPoint = 0.5; const mixedFrame = _utils__WEBPACK_IMPORTED_MODULE_19__["default"].cloneVars(mdVSFrame); mixedFrame.decay = mix * mdVSFrame.decay + mix2 * mdVSFramePrev.decay; mixedFrame.wave_a = mix * mdVSFrame.wave_a + mix2 * mdVSFramePrev.wave_a; mixedFrame.wave_r = mix * mdVSFrame.wave_r + mix2 * mdVSFramePrev.wave_r; mixedFrame.wave_g = mix * mdVSFrame.wave_g + mix2 * mdVSFramePrev.wave_g; mixedFrame.wave_b = mix * mdVSFrame.wave_b + mix2 * mdVSFramePrev.wave_b; mixedFrame.wave_x = mix * mdVSFrame.wave_x + mix2 * mdVSFramePrev.wave_x; mixedFrame.wave_y = mix * mdVSFrame.wave_y + mix2 * mdVSFramePrev.wave_y; mixedFrame.wave_mystery = mix * mdVSFrame.wave_mystery + mix2 * mdVSFramePrev.wave_mystery; mixedFrame.ob_size = mix * mdVSFrame.ob_size + mix2 * mdVSFramePrev.ob_size; mixedFrame.ob_r = mix * mdVSFrame.ob_r + mix2 * mdVSFramePrev.ob_r; mixedFrame.ob_g = mix * mdVSFrame.ob_g + mix2 * mdVSFramePrev.ob_g; mixedFrame.ob_b = mix * mdVSFrame.ob_b + mix2 * mdVSFramePrev.ob_b; mixedFrame.ob_a = mix * mdVSFrame.ob_a + mix2 * mdVSFramePrev.ob_a; mixedFrame.ib_size = mix * mdVSFrame.ib_size + mix2 * mdVSFramePrev.ib_size; mixedFrame.ib_r = mix * mdVSFrame.ib_r + mix2 * mdVSFramePrev.ib_r; mixedFrame.ib_g = mix * mdVSFrame.ib_g + mix2 * mdVSFramePrev.ib_g; mixedFrame.ib_b = mix * mdVSFrame.ib_b + mix2 * mdVSFramePrev.ib_b; mixedFrame.ib_a = mix * mdVSFrame.ib_a + mix2 * mdVSFramePrev.ib_a; mixedFrame.mv_x = mix * mdVSFrame.mv_x + mix2 * mdVSFramePrev.mv_x; mixedFrame.mv_y = mix * mdVSFrame.mv_y + mix2 * mdVSFramePrev.mv_y; mixedFrame.mv_dx = mix * mdVSFrame.mv_dx + mix2 * mdVSFramePrev.mv_dx; mixedFrame.mv_dy = mix * mdVSFrame.mv_dy + mix2 * mdVSFramePrev.mv_dy; mixedFrame.mv_l = mix * mdVSFrame.mv_l + mix2 * mdVSFramePrev.mv_l; mixedFrame.mv_r = mix * mdVSFrame.mv_r + mix2 * mdVSFramePrev.mv_r; mixedFrame.mv_g = mix * mdVSFrame.mv_g + mix2 * mdVSFramePrev.mv_g; mixedFrame.mv_b = mix * mdVSFrame.mv_b + mix2 * mdVSFramePrev.mv_b; mixedFrame.mv_a = mix * mdVSFrame.mv_a + mix2 * mdVSFramePrev.mv_a; mixedFrame.echo_zoom = mix * mdVSFrame.echo_zoom + mix2 * mdVSFramePrev.echo_zoom; mixedFrame.echo_alpha = mix * mdVSFrame.echo_alpha + mix2 * mdVSFramePrev.echo_alpha; mixedFrame.echo_orient = mix * mdVSFrame.echo_orient + mix2 * mdVSFramePrev.echo_orient; mixedFrame.wave_dots = mix < snapPoint ? mdVSFramePrev.wave_dots : mdVSFrame.wave_dots; mixedFrame.wave_thick = mix < snapPoint ? mdVSFramePrev.wave_thick : mdVSFrame.wave_thick; mixedFrame.additivewave = mix < snapPoint ? mdVSFramePrev.additivewave : mdVSFrame.additivewave; mixedFrame.wave_brighten = mix < snapPoint ? mdVSFramePrev.wave_brighten : mdVSFrame.wave_brighten; mixedFrame.darken_center = mix < snapPoint ? mdVSFramePrev.darken_center : mdVSFrame.darken_center; mixedFrame.gammaadj = mix < snapPoint ? mdVSFramePrev.gammaadj : mdVSFrame.gammaadj; mixedFrame.wrap = mix < snapPoint ? mdVSFramePrev.wrap : mdVSFrame.wrap; mixedFrame.invert = mix < snapPoint ? mdVSFramePrev.invert : mdVSFrame.invert; mixedFrame.brighten = mix < snapPoint ? mdVSFramePrev.brighten : mdVSFrame.brighten; mixedFrame.darken = mix < snapPoint ? mdVSFramePrev.darken : mdVSFrame.darken; mixedFrame.solarize = mix < snapPoint ? mdVSFramePrev.brighten : mdVSFrame.solarize; mixedFrame.b1n = mix * mdVSFrame.b1n + mix2 * mdVSFramePrev.b1n; mixedFrame.b2n = mix * mdVSFrame.b2n + mix2 * mdVSFramePrev.b2n; mixedFrame.b3n = mix * mdVSFrame.b3n + mix2 * mdVSFramePrev.b3n; mixedFrame.b1x = mix * mdVSFrame.b1x + mix2 * mdVSFramePrev.b1x; mixedFrame.b2x = mix * mdVSFrame.b2x + mix2 * mdVSFramePrev.b2x; mixedFrame.b3x = mix * mdVSFrame.b3x + mix2 * mdVSFramePrev.b3x; mixedFrame.b1ed = mix * mdVSFrame.b1ed + mix2 * mdVSFramePrev.b1ed; return mixedFrame; } static getBlurValues(mdVSFrame) { let blurMin1 = mdVSFrame.b1n; let blurMin2 = mdVSFrame.b2n; let blurMin3 = mdVSFrame.b3n; let blurMax1 = mdVSFrame.b1x; let blurMax2 = mdVSFrame.b2x; let blurMax3 = mdVSFrame.b3x; const fMinDist = 0.1; if (blurMax1 - blurMin1 < fMinDist) { const avg = (blurMin1 + blurMax1) * 0.5; blurMin1 = avg - fMinDist * 0.5; blurMax1 = avg - fMinDist * 0.5; } blurMax2 = Math.min(blurMax1, blurMax2); blurMin2 = Math.max(blurMin1, blurMin2); if (blurMax2 - blurMin2 < fMinDist) { const avg = (blurMin2 + blurMax2) * 0.5; blurMin2 = avg - fMinDist * 0.5; blurMax2 = avg - fMinDist * 0.5; } blurMax3 = Math.min(blurMax2, blurMax3); blurMin3 = Math.max(blurMin2, blurMin3); if (blurMax3 - blurMin3 < fMinDist) { const avg = (blurMin3 + blurMax3) * 0.5; blurMin3 = avg - fMinDist * 0.5; blurMax3 = avg - fMinDist * 0.5; } return { blurMins: [blurMin1, blurMin2, blurMin3], blurMaxs: [blurMax1, blurMax2, blurMax3] }; } bindFrambufferAndSetViewport(fb, width, height) { this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, fb); this.gl.viewport(0, 0, width, height); } bindFrameBufferTexture(targetFrameBuffer, targetTexture) { this.gl.bindTexture(this.gl.TEXTURE_2D, targetTexture); this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1); this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.texsizeX, this.texsizeY, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, new Uint8Array(this.texsizeX * this.texsizeY * 4)); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); if (this.anisoExt) { const max = this.gl.getParameter(this.anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT); this.gl.texParameterf(this.gl.TEXTURE_2D, this.anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, max); } this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, targetFrameBuffer); this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, targetTexture, 0); } render({ audioLevels, elapsedTime } = {}) { this.calcTimeAndFPS(elapsedTime); this.frameNum += 1; if (audioLevels) { this.audio.updateAudio(audioLevels.timeByteArray, audioLevels.timeByteArrayL, audioLevels.timeByteArrayR); } else { this.audio.sampleAudio(); } this.audioLevels.updateAudioLevels(this.fps, this.frameNum); const globalVars = { frame: this.frameNum, time: this.time, fps: this.fps, bass: this.audioLevels.bass, bass_att: this.audioLevels.bass_att, mid: this.audioLevels.mid, mid_att: this.audioLevels.mid_att, treb: this.audioLevels.treb, treb_att: this.audioLevels.treb_att, meshx: this.mesh_width, meshy: this.mesh_height, aspectx: this.invAspectx, aspecty: this.invAspecty, pixelsx: this.texsizeX, pixelsy: this.texsizeY }; const prevGlobalVars = Object.assign({}, globalVars); if (!this.prevPreset.useWASM) { prevGlobalVars.gmegabuf = this.prevPresetEquationRunner.gmegabuf; } if (!this.preset.useWASM) { globalVars.gmegabuf = this.presetEquationRunner.gmegabuf; Object.assign(globalVars, this.regVars); } const mdVSFrame = this.presetEquationRunner.runFrameEquations(globalVars); this.runPixelEquations(this.presetEquationRunner, mdVSFrame, globalVars, false); if (!this.preset.useWASM) { Object.assign(this.regVars, _utils__WEBPACK_IMPORTED_MODULE_19__["default"].pick(this.mdVSVertex, this.regs)); Object.assign(globalVars, this.regVars); } let mdVSFrameMixed; if (this.blending) { this.prevMDVSFrame = this.prevPresetEquationRunner.runFrameEquations(prevGlobalVars); this.runPixelEquations(this.prevPresetEquationRunner, this.prevMDVSFrame, prevGlobalVars, true); mdVSFrameMixed = Renderer.mixFrameEquations(this.blendProgress, mdVSFrame, this.prevMDVSFrame); } else { mdVSFrameMixed = mdVSFrame; } const swapTexture = this.targetTexture; this.targetTexture = this.prevTexture; this.prevTexture = swapTexture; const swapFrameBuffer = this.targetFrameBuffer; this.targetFrameBuffer = this.prevFrameBuffer; this.prevFrameBuffer = swapFrameBuffer; this.gl.bindTexture(this.gl.TEXTURE_2D, this.prevTexture); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.bindFrambufferAndSetViewport(this.targetFrameBuffer, this.texsizeX, this.texsizeY); this.gl.clear(this.gl.COLOR_BUFFER_BIT); this.gl.enable(this.gl.BLEND); this.gl.blendEquation(this.gl.FUNC_ADD); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); const { blurMins, blurMaxs } = Renderer.getBlurValues(mdVSFrameMixed); if (!this.blending) { this.warpShader.renderQuadTexture(false, this.prevTexture, this.blurTexture1, this.blurTexture2, this.blurTexture3, blurMins, blurMaxs, mdVSFrame, this.presetEquationRunner.mdVSQAfterFrame, this.warpUVs, this.warpColor); } else { this.prevWarpShader.renderQuadTexture(false, this.prevTexture, this.blurTexture1, this.blurTexture2, this.blurTexture3, blurMins, blurMaxs, this.prevMDVSFrame, this.prevPresetEquationRunner.mdVSQAfterFrame, this.warpUVs, this.warpColor); this.warpShader.renderQuadTexture(true, this.prevTexture, this.blurTexture1, this.blurTexture2, this.blurTexture3, blurMins, blurMaxs, mdVSFrameMixed, this.presetEquationRunner.mdVSQAfterFrame, this.warpUVs, this.warpColor); } if (this.numBlurPasses > 0) { this.blurShader1.renderBlurTexture(this.targetTexture, mdVSFrame, blurMins, blurMaxs); if (this.numBlurPasses > 1) { this.blurShader2.renderBlurTexture(this.blurTexture1, mdVSFrame, blurMins, blurMaxs); if (this.numBlurPasses > 2) { this.blurShader3.renderBlurTexture(this.blurTexture2, mdVSFrame, blurMins, blurMaxs); } } // rebind target texture framebuffer this.bindFrambufferAndSetViewport(this.targetFrameBuffer, this.texsizeX, this.texsizeY); } this.motionVectors.drawMotionVectors(mdVSFrameMixed, this.warpUVs); if (this.preset.shapes && this.preset.shapes.length > 0) { this.customShapes.forEach((shape, i) => { shape.drawCustomShape(this.blending ? this.blendProgress : 1, globalVars, this.presetEquationRunner, this.preset.shapes[i], this.prevTexture); }); } if (this.preset.waves && this.preset.waves.length > 0) { this.customWaveforms.forEach((waveform, i) => { waveform.drawCustomWaveform(this.blending ? this.blendProgress : 1, this.audio.timeArrayL, this.audio.timeArrayR, this.audio.freqArrayL, this.audio.freqArrayR, globalVars, this.presetEquationRunner, this.preset.waves[i]); }); } if (this.blending) { if (this.prevPreset.shapes && this.prevPreset.shapes.length > 0) { this.prevCustomShapes.forEach((shape, i) => { shape.drawCustomShape(1.0 - this.blendProgress, prevGlobalVars, this.prevPresetEquationRunner, this.prevPreset.shapes[i], this.prevTexture); }); } if (this.prevPreset.waves && this.prevPreset.waves.length > 0) { this.prevCustomWaveforms.forEach((waveform, i) => { waveform.drawCustomWaveform(1.0 - this.blendProgress, this.audio.timeArrayL, this.audio.timeArrayR, this.audio.freqArrayL, this.audio.freqArrayR, prevGlobalVars, this.prevPresetEquationRunner, this.prevPreset.waves[i]); }); } } this.basicWaveform.drawBasicWaveform(this.blending, this.blendProgress, this.audio.timeArrayL, this.audio.timeArrayR, mdVSFrameMixed); this.darkenCenter.drawDarkenCenter(mdVSFrameMixed); const outerColor = [mdVSFrameMixed.ob_r, mdVSFrameMixed.ob_g, mdVSFrameMixed.ob_b, mdVSFrameMixed.ob_a]; this.outerBorder.drawBorder(outerColor, mdVSFrameMixed.ob_size, 0); const innerColor = [mdVSFrameMixed.ib_r, mdVSFrameMixed.ib_g, mdVSFrameMixed.ib_b, mdVSFrameMixed.ib_a]; this.innerBorder.drawBorder(innerColor, mdVSFrameMixed.ib_size, mdVSFrameMixed.ob_size); if (this.supertext.startTime >= 0) { const progress = (this.time - this.supertext.startTime) / this.supertext.duration; if (progress >= 1) { this.titleText.renderTitle(progress, true, globalVars); } } // Store variables in case we need to rerender this.globalVars = globalVars; this.mdVSFrame = mdVSFrame; this.mdVSFrameMixed = mdVSFrameMixed; this.renderToScreen(); } renderToScreen() { if (this.outputFXAA) { this.bindFrambufferAndSetViewport(this.compFrameBuffer, this.texsizeX, this.texsizeY); } else { this.bindFrambufferAndSetViewport(null, this.width, this.height); } this.gl.clear(this.gl.COLOR_BUFFER_BIT); this.gl.enable(this.gl.BLEND); this.gl.blendEquation(this.gl.FUNC_ADD); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); const { blurMins, blurMaxs } = Renderer.getBlurValues(this.mdVSFrameMixed); if (!this.blending) { this.compShader.renderQuadTexture(false, this.targetTexture, this.blurTexture1, this.blurTexture2, this.blurTexture3, blurMins, blurMaxs, this.mdVSFrame, this.presetEquationRunner.mdVSQAfterFrame, this.warpColor); } else { this.prevCompShader.renderQuadTexture(false, this.targetTexture, this.blurTexture1, this.blurTexture2, this.blurTexture3, blurMins, blurMaxs, this.prevMDVSFrame, this.prevPresetEquationRunner.mdVSQAfterFrame, this.warpColor); this.compShader.renderQuadTexture(true, this.targetTexture, this.blurTexture1, this.blurTexture2, this.blurTexture3, blurMins, blurMaxs, this.mdVSFrameMixed, this.presetEquationRunner.mdVSQAfterFrame, this.warpColor); } if (this.supertext.startTime >= 0) { const progress = (this.time - this.supertext.startTime) / this.supertext.duration; this.titleText.renderTitle(progress, false, this.globalVars); if (progress >= 1) { this.supertext.startTime = -1; } } if (this.outputFXAA) { this.gl.bindTexture(this.gl.TEXTURE_2D, this.compTexture); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.bindFrambufferAndSetViewport(null, this.width, this.height); this.outputShader.renderQuadTexture(this.compTexture); } } launchSongTitleAnim(text) { this.supertext = { startTime: this.time, duration: 1.7 }; this.titleText.generateTitleTexture(text); } toDataURL() { const data = new Uint8Array(this.texsizeX * this.texsizeY * 4); const compFrameBuffer = this.gl.createFramebuffer(); const compTexture = this.gl.createTexture(); this.bindFrameBufferTexture(compFrameBuffer, compTexture); const { blurMins, blurMaxs } = Renderer.getBlurValues(this.mdVSFrameMixed); this.compShader.renderQuadTexture(false, this.targetTexture, this.blurTexture1, this.blurTexture2, this.blurTexture3, blurMins, blurMaxs, this.mdVSFrame, this.presetEquationRunner.mdVSQAfterFrame, this.warpColor); this.gl.readPixels(0, 0, this.texsizeX, this.texsizeY, this.gl.RGBA, this.gl.UNSIGNED_BYTE, data); // flip data Array.from({ length: this.texsizeY }, (val, i) => data.slice(i * this.texsizeX * 4, (i + 1) * this.texsizeX * 4)).forEach((val, i) => data.set(val, (this.texsizeY - i - 1) * this.texsizeX * 4)); const canvas = document.createElement("canvas"); canvas.width = this.texsizeX; canvas.height = this.texsizeY; const context = canvas.getContext("2d"); const imageData = context.createImageData(this.texsizeX, this.texsizeY); imageData.data.set(data); context.putImageData(imageData, 0, 0); this.gl.deleteTexture(compTexture); this.gl.deleteFramebuffer(compFrameBuffer); return canvas.toDataURL(); } warpBufferToDataURL() { const data = new Uint8Array(this.texsizeX * this.texsizeY * 4); this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.targetFrameBuffer); this.gl.readPixels(0, 0, this.texsizeX, this.texsizeY, this.gl.RGBA, this.gl.UNSIGNED_BYTE, data); const canvas = document.createElement("canvas"); canvas.width = this.texsizeX; canvas.height = this.texsizeY; const context = canvas.getContext("2d"); const imageData = context.createImageData(this.texsizeX, this.texsizeY); imageData.data.set(data); context.putImageData(imageData, 0, 0); return canvas.toDataURL(); } } /***/ }), /***/ "./src/rendering/shaders/blur/blur.js": /*!********************************************!*\ !*** ./src/rendering/shaders/blur/blur.js ***! \********************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return BlurShader; }); /* harmony import */ var _blurVertical__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./blurVertical */ "./src/rendering/shaders/blur/blurVertical.js"); /* harmony import */ var _blurHorizontal__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./blurHorizontal */ "./src/rendering/shaders/blur/blurHorizontal.js"); class BlurShader { constructor(blurLevel, blurRatios, gl, opts = {}) { this.blurLevel = blurLevel; this.blurRatios = blurRatios; this.gl = gl; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.anisoExt = this.gl.getExtension("EXT_texture_filter_anisotropic") || this.gl.getExtension("MOZ_EXT_texture_filter_anisotropic") || this.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); this.blurHorizontalFrameBuffer = this.gl.createFramebuffer(); this.blurVerticalFrameBuffer = this.gl.createFramebuffer(); this.blurHorizontalTexture = this.gl.createTexture(); this.blurVerticalTexture = this.gl.createTexture(); this.setupFrameBufferTextures(); this.blurHorizontal = new _blurHorizontal__WEBPACK_IMPORTED_MODULE_1__["default"](gl, this.blurLevel, opts); this.blurVertical = new _blurVertical__WEBPACK_IMPORTED_MODULE_0__["default"](gl, this.blurLevel, opts); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.setupFrameBufferTextures(); } getTextureSize(sizeRatio) { let sizeX = Math.max(this.texsizeX * sizeRatio, 16); sizeX = Math.floor((sizeX + 3) / 16) * 16; let sizeY = Math.max(this.texsizeY * sizeRatio, 16); sizeY = Math.floor((sizeY + 3) / 4) * 4; return [sizeX, sizeY]; } setupFrameBufferTextures() { const srcBlurRatios = this.blurLevel > 0 ? this.blurRatios[this.blurLevel - 1] : [1, 1]; const dstBlurRatios = this.blurRatios[this.blurLevel]; const srcTexsizeHorizontal = this.getTextureSize(srcBlurRatios[1]); const dstTexsizeHorizontal = this.getTextureSize(dstBlurRatios[0]); this.bindFrameBufferTexture(this.blurHorizontalFrameBuffer, this.blurHorizontalTexture, dstTexsizeHorizontal); const srcTexsizeVertical = dstTexsizeHorizontal; const dstTexsizeVertical = this.getTextureSize(dstBlurRatios[1]); this.bindFrameBufferTexture(this.blurVerticalFrameBuffer, this.blurVerticalTexture, dstTexsizeVertical); this.horizontalTexsizes = [srcTexsizeHorizontal, dstTexsizeHorizontal]; this.verticalTexsizes = [srcTexsizeVertical, dstTexsizeVertical]; } bindFrambufferAndSetViewport(fb, texsize) { this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, fb); this.gl.viewport(0, 0, texsize[0], texsize[1]); } bindFrameBufferTexture(targetFrameBuffer, targetTexture, texsize) { this.gl.bindTexture(this.gl.TEXTURE_2D, targetTexture); this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1); this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, texsize[0], texsize[1], 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, new Uint8Array(texsize[0] * texsize[1] * 4)); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); if (this.anisoExt) { const max = this.gl.getParameter(this.anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT); this.gl.texParameterf(this.gl.TEXTURE_2D, this.anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, max); } this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, targetFrameBuffer); this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, targetTexture, 0); } renderBlurTexture(prevTexture, mdVSFrame, blurMins, blurMaxs) { this.bindFrambufferAndSetViewport(this.blurHorizontalFrameBuffer, this.horizontalTexsizes[1]); this.blurHorizontal.renderQuadTexture(prevTexture, mdVSFrame, blurMins, blurMaxs, this.horizontalTexsizes[0]); this.gl.bindTexture(this.gl.TEXTURE_2D, this.blurHorizontalTexture); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.bindFrambufferAndSetViewport(this.blurVerticalFrameBuffer, this.verticalTexsizes[1]); this.blurVertical.renderQuadTexture(this.blurHorizontalTexture, mdVSFrame, this.verticalTexsizes[0]); this.gl.bindTexture(this.gl.TEXTURE_2D, this.blurVerticalTexture); this.gl.generateMipmap(this.gl.TEXTURE_2D); } } /***/ }), /***/ "./src/rendering/shaders/blur/blurHorizontal.js": /*!******************************************************!*\ !*** ./src/rendering/shaders/blur/blurHorizontal.js ***! \******************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return BlurHorizontal; }); /* harmony import */ var _shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class BlurHorizontal { constructor(gl, blurLevel) { this.gl = gl; this.blurLevel = blurLevel; const w = [4.0, 3.8, 3.5, 2.9, 1.9, 1.2, 0.7, 0.3]; const w1H = w[0] + w[1]; const w2H = w[2] + w[3]; const w3H = w[4] + w[5]; const w4H = w[6] + w[7]; const d1H = 0 + 2 * w[1] / w1H; const d2H = 2 + 2 * w[3] / w2H; const d3H = 4 + 2 * w[5] / w3H; const d4H = 6 + 2 * w[7] / w4H; this.ws = new Float32Array([w1H, w2H, w3H, w4H]); this.ds = new Float32Array([d1H, d2H, d3H, d4H]); this.wDiv = 0.5 / (w1H + w2H + w3H + w4H); this.positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); this.vertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es const vec2 halfmad = vec2(0.5); in vec2 aPos; out vec2 uv; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); uv = aPos * halfmad + halfmad; } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, `#version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec2 uv; out vec4 fragColor; uniform sampler2D uTexture; uniform vec4 texsize; uniform float scale; uniform float bias; uniform vec4 ws; uniform vec4 ds; uniform float wdiv; void main(void) { float w1 = ws[0]; float w2 = ws[1]; float w3 = ws[2]; float w4 = ws[3]; float d1 = ds[0]; float d2 = ds[1]; float d3 = ds[2]; float d4 = ds[3]; vec2 uv2 = uv.xy; vec3 blur = ( texture(uTexture, uv2 + vec2( d1 * texsize.z,0.0) ).xyz + texture(uTexture, uv2 + vec2(-d1 * texsize.z,0.0) ).xyz) * w1 + ( texture(uTexture, uv2 + vec2( d2 * texsize.z,0.0) ).xyz + texture(uTexture, uv2 + vec2(-d2 * texsize.z,0.0) ).xyz) * w2 + ( texture(uTexture, uv2 + vec2( d3 * texsize.z,0.0) ).xyz + texture(uTexture, uv2 + vec2(-d3 * texsize.z,0.0) ).xyz) * w3 + ( texture(uTexture, uv2 + vec2( d4 * texsize.z,0.0) ).xyz + texture(uTexture, uv2 + vec2(-d4 * texsize.z,0.0) ).xyz) * w4; blur.xyz *= wdiv; blur.xyz = blur.xyz * scale + bias; fragColor = vec4(blur, 1.0); }`); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "uTexture"); this.texsizeLocation = this.gl.getUniformLocation(this.shaderProgram, "texsize"); this.scaleLoc = this.gl.getUniformLocation(this.shaderProgram, "scale"); this.biasLoc = this.gl.getUniformLocation(this.shaderProgram, "bias"); this.wsLoc = this.gl.getUniformLocation(this.shaderProgram, "ws"); this.dsLocation = this.gl.getUniformLocation(this.shaderProgram, "ds"); this.wdivLoc = this.gl.getUniformLocation(this.shaderProgram, "wdiv"); } getScaleAndBias(blurMins, blurMaxs) { const scale = [1, 1, 1]; const bias = [0, 0, 0]; let tempMin; let tempMax; scale[0] = 1.0 / (blurMaxs[0] - blurMins[0]); bias[0] = -blurMins[0] * scale[0]; tempMin = (blurMins[1] - blurMins[0]) / (blurMaxs[0] - blurMins[0]); tempMax = (blurMaxs[1] - blurMins[0]) / (blurMaxs[0] - blurMins[0]); scale[1] = 1.0 / (tempMax - tempMin); bias[1] = -tempMin * scale[1]; tempMin = (blurMins[2] - blurMins[1]) / (blurMaxs[1] - blurMins[1]); tempMax = (blurMaxs[2] - blurMins[1]) / (blurMaxs[1] - blurMins[1]); scale[2] = 1.0 / (tempMax - tempMin); bias[2] = -tempMin * scale[2]; return { scale: scale[this.blurLevel], bias: bias[this.blurLevel] }; } renderQuadTexture(texture, mdVSFrame, blurMins, blurMaxs, srcTexsize) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.positionLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.positionLocation); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.uniform1i(this.textureLoc, 0); const { scale, bias } = this.getScaleAndBias(blurMins, blurMaxs); this.gl.uniform4fv(this.texsizeLocation, [srcTexsize[0], srcTexsize[1], 1.0 / srcTexsize[0], 1.0 / srcTexsize[1]]); this.gl.uniform1f(this.scaleLoc, scale); this.gl.uniform1f(this.biasLoc, bias); this.gl.uniform4fv(this.wsLoc, this.ws); this.gl.uniform4fv(this.dsLocation, this.ds); this.gl.uniform1f(this.wdivLoc, this.wDiv); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4); } } /***/ }), /***/ "./src/rendering/shaders/blur/blurVertical.js": /*!****************************************************!*\ !*** ./src/rendering/shaders/blur/blurVertical.js ***! \****************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return BlurVertical; }); /* harmony import */ var _shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class BlurVertical { constructor(gl, blurLevel) { this.gl = gl; this.blurLevel = blurLevel; const w = [4.0, 3.8, 3.5, 2.9, 1.9, 1.2, 0.7, 0.3]; const w1V = w[0] + w[1] + w[2] + w[3]; const w2V = w[4] + w[5] + w[6] + w[7]; const d1V = 0 + 2 * ((w[2] + w[3]) / w1V); const d2V = 2 + 2 * ((w[6] + w[7]) / w2V); this.wds = new Float32Array([w1V, w2V, d1V, d2V]); this.wDiv = 1.0 / ((w1V + w2V) * 2); this.positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); this.vertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es const vec2 halfmad = vec2(0.5); in vec2 aPos; out vec2 uv; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); uv = aPos * halfmad + halfmad; } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, `#version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec2 uv; out vec4 fragColor; uniform sampler2D uTexture; uniform vec4 texsize; uniform float ed1; uniform float ed2; uniform float ed3; uniform vec4 wds; uniform float wdiv; void main(void) { float w1 = wds[0]; float w2 = wds[1]; float d1 = wds[2]; float d2 = wds[3]; vec2 uv2 = uv.xy; vec3 blur = ( texture(uTexture, uv2 + vec2(0.0, d1 * texsize.w) ).xyz + texture(uTexture, uv2 + vec2(0.0,-d1 * texsize.w) ).xyz) * w1 + ( texture(uTexture, uv2 + vec2(0.0, d2 * texsize.w) ).xyz + texture(uTexture, uv2 + vec2(0.0,-d2 * texsize.w) ).xyz) * w2; blur.xyz *= wdiv; float t = min(min(uv.x, uv.y), 1.0 - max(uv.x, uv.y)); t = sqrt(t); t = ed1 + ed2 * clamp(t * ed3, 0.0, 1.0); blur.xyz *= t; fragColor = vec4(blur, 1.0); }`); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "uTexture"); this.texsizeLocation = this.gl.getUniformLocation(this.shaderProgram, "texsize"); this.ed1Loc = this.gl.getUniformLocation(this.shaderProgram, "ed1"); this.ed2Loc = this.gl.getUniformLocation(this.shaderProgram, "ed2"); this.ed3Loc = this.gl.getUniformLocation(this.shaderProgram, "ed3"); this.wdsLocation = this.gl.getUniformLocation(this.shaderProgram, "wds"); this.wdivLoc = this.gl.getUniformLocation(this.shaderProgram, "wdiv"); } renderQuadTexture(texture, mdVSFrame, srcTexsize) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.positionLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.positionLocation); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.uniform1i(this.textureLoc, 0); const b1ed = this.blurLevel === 0 ? mdVSFrame.b1ed : 0.0; this.gl.uniform4fv(this.texsizeLocation, [srcTexsize[0], srcTexsize[1], 1.0 / srcTexsize[0], 1.0 / srcTexsize[1]]); this.gl.uniform1f(this.ed1Loc, 1.0 - b1ed); this.gl.uniform1f(this.ed2Loc, b1ed); this.gl.uniform1f(this.ed3Loc, 5.0); this.gl.uniform4fv(this.wdsLocation, this.wds); this.gl.uniform1f(this.wdivLoc, this.wDiv); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4); } } /***/ }), /***/ "./src/rendering/shaders/comp.js": /*!***************************************!*\ !*** ./src/rendering/shaders/comp.js ***! \***************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return CompShader; }); /* harmony import */ var _shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class CompShader { constructor(gl, noise, image, opts = {}) { this.gl = gl; this.noise = noise; this.image = image; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.compWidth = 32; this.compHeight = 24; this.buildPositions(); this.indexBuf = gl.createBuffer(); this.positionVertexBuf = this.gl.createBuffer(); this.compColorVertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); this.mainSampler = this.gl.createSampler(); this.mainSamplerFW = this.gl.createSampler(); this.mainSamplerFC = this.gl.createSampler(); this.mainSamplerPW = this.gl.createSampler(); this.mainSamplerPC = this.gl.createSampler(); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); } // based on https://github.com/mrdoob/three.js/blob/master/src/geometries/PlaneGeometry.js buildPositions() { const width = 2; const height = 2; const widthHalf = width / 2; const heightHalf = height / 2; const gridX = this.compWidth; const gridY = this.compHeight; const gridX1 = gridX + 1; const gridY1 = gridY + 1; const segmentWidth = width / gridX; const segmentHeight = height / gridY; const vertices = []; for (let iy = 0; iy < gridY1; iy++) { const y = iy * segmentHeight - heightHalf; for (let ix = 0; ix < gridX1; ix++) { const x = ix * segmentWidth - widthHalf; vertices.push(x, -y, 0); } } const indices = []; for (let iy = 0; iy < gridY; iy++) { for (let ix = 0; ix < gridX; ix++) { const a = ix + gridX1 * iy; const b = ix + gridX1 * (iy + 1); const c = ix + 1 + gridX1 * (iy + 1); const d = ix + 1 + gridX1 * iy; indices.push(a, b, d); indices.push(b, c, d); } } this.vertices = new Float32Array(vertices); this.indices = new Uint16Array(indices); } updateGlobals(opts) { this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.buildPositions(); } createShader(shaderText = "") { let fragShaderText; let fragShaderHeaderText; if (shaderText.length === 0) { fragShaderText = `float orient_horiz = mod(echo_orientation, 2.0); float orient_x = (orient_horiz != 0.0) ? -1.0 : 1.0; float orient_y = (echo_orientation >= 2.0) ? -1.0 : 1.0; vec2 uv_echo = ((uv - 0.5) * (1.0 / echo_zoom) * vec2(orient_x, orient_y)) + 0.5; ret = mix(texture(sampler_main, uv).rgb, texture(sampler_main, uv_echo).rgb, echo_alpha); ret *= gammaAdj; if(fShader >= 1.0) { ret *= hue_shader; } else if(fShader > 0.001) { ret *= (1.0 - fShader) + (fShader * hue_shader); } if(brighten != 0) ret = sqrt(ret); if(darken != 0) ret = ret*ret; if(solarize != 0) ret = ret * (1.0 - ret) * 4.0; if(invert != 0) ret = 1.0 - ret;`; fragShaderHeaderText = ""; } else { const shaderParts = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getShaderParts(shaderText); fragShaderHeaderText = shaderParts[0]; fragShaderText = shaderParts[1]; } fragShaderText = fragShaderText.replace(/texture2D/g, "texture"); fragShaderText = fragShaderText.replace(/texture3D/g, "texture"); this.userTextures = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getUserSamplers(fragShaderHeaderText); this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es const vec2 halfmad = vec2(0.5); in vec2 aPos; in vec4 aCompColor; out vec2 vUv; out vec4 vColor; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); vUv = aPos * halfmad + halfmad; vColor = aCompColor; } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; precision mediump sampler3D; vec3 lum(vec3 v){ return vec3(dot(v, vec3(0.32,0.49,0.29))); } in vec2 vUv; in vec4 vColor; out vec4 fragColor; uniform sampler2D sampler_main; uniform sampler2D sampler_fw_main; uniform sampler2D sampler_fc_main; uniform sampler2D sampler_pw_main; uniform sampler2D sampler_pc_main; uniform sampler2D sampler_blur1; uniform sampler2D sampler_blur2; uniform sampler2D sampler_blur3; uniform sampler2D sampler_noise_lq; uniform sampler2D sampler_noise_lq_lite; uniform sampler2D sampler_noise_mq; uniform sampler2D sampler_noise_hq; uniform sampler2D sampler_pw_noise_lq; uniform sampler3D sampler_noisevol_lq; uniform sampler3D sampler_noisevol_hq; uniform float time; uniform float gammaAdj; uniform float echo_zoom; uniform float echo_alpha; uniform float echo_orientation; uniform int invert; uniform int brighten; uniform int darken; uniform int solarize; uniform vec2 resolution; uniform vec4 aspect; uniform vec4 texsize; uniform vec4 texsize_noise_lq; uniform vec4 texsize_noise_mq; uniform vec4 texsize_noise_hq; uniform vec4 texsize_noise_lq_lite; uniform vec4 texsize_noisevol_lq; uniform vec4 texsize_noisevol_hq; uniform float bass; uniform float mid; uniform float treb; uniform float vol; uniform float bass_att; uniform float mid_att; uniform float treb_att; uniform float vol_att; uniform float frame; uniform float fps; uniform vec4 _qa; uniform vec4 _qb; uniform vec4 _qc; uniform vec4 _qd; uniform vec4 _qe; uniform vec4 _qf; uniform vec4 _qg; uniform vec4 _qh; #define q1 _qa.x #define q2 _qa.y #define q3 _qa.z #define q4 _qa.w #define q5 _qb.x #define q6 _qb.y #define q7 _qb.z #define q8 _qb.w #define q9 _qc.x #define q10 _qc.y #define q11 _qc.z #define q12 _qc.w #define q13 _qd.x #define q14 _qd.y #define q15 _qd.z #define q16 _qd.w #define q17 _qe.x #define q18 _qe.y #define q19 _qe.z #define q20 _qe.w #define q21 _qf.x #define q22 _qf.y #define q23 _qf.z #define q24 _qf.w #define q25 _qg.x #define q26 _qg.y #define q27 _qg.z #define q28 _qg.w #define q29 _qh.x #define q30 _qh.y #define q31 _qh.z #define q32 _qh.w uniform vec4 slow_roam_cos; uniform vec4 roam_cos; uniform vec4 slow_roam_sin; uniform vec4 roam_sin; uniform float blur1_min; uniform float blur1_max; uniform float blur2_min; uniform float blur2_max; uniform float blur3_min; uniform float blur3_max; uniform float scale1; uniform float scale2; uniform float scale3; uniform float bias1; uniform float bias2; uniform float bias3; uniform vec4 rand_frame; uniform vec4 rand_preset; uniform float fShader; float PI = ${Math.PI}; ${fragShaderHeaderText} void main(void) { vec3 ret; vec2 uv = vUv; vec2 uv_orig = vUv; uv.y = 1.0 - uv.y; uv_orig.y = 1.0 - uv_orig.y; float rad = length(uv - 0.5); float ang = atan(uv.x - 0.5, uv.y - 0.5); vec3 hue_shader = vColor.rgb; ${fragShaderText} fragColor = vec4(ret, vColor.a); } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.compColorLocation = this.gl.getAttribLocation(this.shaderProgram, "aCompColor"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_main"); this.textureFWLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_fw_main"); this.textureFCLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_fc_main"); this.texturePWLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_pw_main"); this.texturePCLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_pc_main"); this.blurTexture1Loc = this.gl.getUniformLocation(this.shaderProgram, "sampler_blur1"); this.blurTexture2Loc = this.gl.getUniformLocation(this.shaderProgram, "sampler_blur2"); this.blurTexture3Loc = this.gl.getUniformLocation(this.shaderProgram, "sampler_blur3"); this.noiseLQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_lq"); this.noiseMQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_mq"); this.noiseHQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_hq"); this.noiseLQLiteLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_lq_lite"); this.noisePointLQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_pw_noise_lq"); this.noiseVolLQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noisevol_lq"); this.noiseVolHQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noisevol_hq"); this.timeLoc = this.gl.getUniformLocation(this.shaderProgram, "time"); this.gammaAdjLoc = this.gl.getUniformLocation(this.shaderProgram, "gammaAdj"); this.echoZoomLoc = this.gl.getUniformLocation(this.shaderProgram, "echo_zoom"); this.echoAlphaLoc = this.gl.getUniformLocation(this.shaderProgram, "echo_alpha"); this.echoOrientationLoc = this.gl.getUniformLocation(this.shaderProgram, "echo_orientation"); this.invertLoc = this.gl.getUniformLocation(this.shaderProgram, "invert"); this.brightenLoc = this.gl.getUniformLocation(this.shaderProgram, "brighten"); this.darkenLoc = this.gl.getUniformLocation(this.shaderProgram, "darken"); this.solarizeLoc = this.gl.getUniformLocation(this.shaderProgram, "solarize"); this.texsizeLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize"); this.texsizeNoiseLQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_lq"); this.texsizeNoiseMQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_mq"); this.texsizeNoiseHQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_hq"); this.texsizeNoiseLQLiteLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_lq_lite"); this.texsizeNoiseVolLQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noisevol_lq"); this.texsizeNoiseVolHQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noisevol_hq"); this.resolutionLoc = this.gl.getUniformLocation(this.shaderProgram, "resolution"); this.aspectLoc = this.gl.getUniformLocation(this.shaderProgram, "aspect"); this.bassLoc = this.gl.getUniformLocation(this.shaderProgram, "bass"); this.midLoc = this.gl.getUniformLocation(this.shaderProgram, "mid"); this.trebLoc = this.gl.getUniformLocation(this.shaderProgram, "treb"); this.volLoc = this.gl.getUniformLocation(this.shaderProgram, "vol"); this.bassAttLoc = this.gl.getUniformLocation(this.shaderProgram, "bass_att"); this.midAttLoc = this.gl.getUniformLocation(this.shaderProgram, "mid_att"); this.trebAttLoc = this.gl.getUniformLocation(this.shaderProgram, "treb_att"); this.volAttLoc = this.gl.getUniformLocation(this.shaderProgram, "vol_att"); this.frameLoc = this.gl.getUniformLocation(this.shaderProgram, "frame"); this.fpsLoc = this.gl.getUniformLocation(this.shaderProgram, "fps"); this.blur1MinLoc = this.gl.getUniformLocation(this.shaderProgram, "blur1_min"); this.blur1MaxLoc = this.gl.getUniformLocation(this.shaderProgram, "blur1_max"); this.blur2MinLoc = this.gl.getUniformLocation(this.shaderProgram, "blur2_min"); this.blur2MaxLoc = this.gl.getUniformLocation(this.shaderProgram, "blur2_max"); this.blur3MinLoc = this.gl.getUniformLocation(this.shaderProgram, "blur3_min"); this.blur3MaxLoc = this.gl.getUniformLocation(this.shaderProgram, "blur3_max"); this.scale1Loc = this.gl.getUniformLocation(this.shaderProgram, "scale1"); this.scale2Loc = this.gl.getUniformLocation(this.shaderProgram, "scale2"); this.scale3Loc = this.gl.getUniformLocation(this.shaderProgram, "scale3"); this.bias1Loc = this.gl.getUniformLocation(this.shaderProgram, "bias1"); this.bias2Loc = this.gl.getUniformLocation(this.shaderProgram, "bias2"); this.bias3Loc = this.gl.getUniformLocation(this.shaderProgram, "bias3"); this.randPresetLoc = this.gl.getUniformLocation(this.shaderProgram, "rand_preset"); this.randFrameLoc = this.gl.getUniformLocation(this.shaderProgram, "rand_frame"); this.fShaderLoc = this.gl.getUniformLocation(this.shaderProgram, "fShader"); this.qaLoc = this.gl.getUniformLocation(this.shaderProgram, "_qa"); this.qbLoc = this.gl.getUniformLocation(this.shaderProgram, "_qb"); this.qcLoc = this.gl.getUniformLocation(this.shaderProgram, "_qc"); this.qdLoc = this.gl.getUniformLocation(this.shaderProgram, "_qd"); this.qeLoc = this.gl.getUniformLocation(this.shaderProgram, "_qe"); this.qfLoc = this.gl.getUniformLocation(this.shaderProgram, "_qf"); this.qgLoc = this.gl.getUniformLocation(this.shaderProgram, "_qg"); this.qhLoc = this.gl.getUniformLocation(this.shaderProgram, "_qh"); this.slowRoamCosLoc = this.gl.getUniformLocation(this.shaderProgram, "slow_roam_cos"); this.roamCosLoc = this.gl.getUniformLocation(this.shaderProgram, "roam_cos"); this.slowRoamSinLoc = this.gl.getUniformLocation(this.shaderProgram, "slow_roam_sin"); this.roamSinLoc = this.gl.getUniformLocation(this.shaderProgram, "roam_sin"); for (let i = 0; i < this.userTextures.length; i++) { const userTexture = this.userTextures[i]; userTexture.textureLoc = this.gl.getUniformLocation(this.shaderProgram, `sampler_${userTexture.sampler}`); } } updateShader(shaderText) { this.createShader(shaderText); } bindBlurVals(blurMins, blurMaxs) { const blurMin1 = blurMins[0]; const blurMin2 = blurMins[1]; const blurMin3 = blurMins[2]; const blurMax1 = blurMaxs[0]; const blurMax2 = blurMaxs[1]; const blurMax3 = blurMaxs[2]; const scale1 = blurMax1 - blurMin1; const bias1 = blurMin1; const scale2 = blurMax2 - blurMin2; const bias2 = blurMin2; const scale3 = blurMax3 - blurMin3; const bias3 = blurMin3; this.gl.uniform1f(this.blur1MinLoc, blurMin1); this.gl.uniform1f(this.blur1MaxLoc, blurMax1); this.gl.uniform1f(this.blur2MinLoc, blurMin2); this.gl.uniform1f(this.blur2MaxLoc, blurMax2); this.gl.uniform1f(this.blur3MinLoc, blurMin3); this.gl.uniform1f(this.blur3MaxLoc, blurMax3); this.gl.uniform1f(this.scale1Loc, scale1); this.gl.uniform1f(this.scale2Loc, scale2); this.gl.uniform1f(this.scale3Loc, scale3); this.gl.uniform1f(this.bias1Loc, bias1); this.gl.uniform1f(this.bias2Loc, bias2); this.gl.uniform1f(this.bias3Loc, bias3); } static generateHueBase(mdVSFrame) { const hueBase = new Float32Array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); /* eslint-disable max-len */ for (let i = 0; i < 4; i++) { hueBase[i * 3 + 0] = 0.6 + 0.3 * Math.sin(mdVSFrame.time * 30.0 * 0.0143 + 3 + i * 21 + mdVSFrame.rand_start[3]); hueBase[i * 3 + 1] = 0.6 + 0.3 * Math.sin(mdVSFrame.time * 30.0 * 0.0107 + 1 + i * 13 + mdVSFrame.rand_start[1]); hueBase[i * 3 + 2] = 0.6 + 0.3 * Math.sin(mdVSFrame.time * 30.0 * 0.0129 + 6 + i * 9 + mdVSFrame.rand_start[2]); const maxshade = Math.max(hueBase[i * 3], hueBase[i * 3 + 1], hueBase[i * 3 + 2]); for (let k = 0; k < 3; k++) { hueBase[i * 3 + k] = hueBase[i * 3 + k] / maxshade; hueBase[i * 3 + k] = 0.5 + 0.5 * hueBase[i * 3 + k]; } } /* eslint-enable max-len */ return hueBase; } generateCompColors(blending, mdVSFrame, warpColor) { const hueBase = CompShader.generateHueBase(mdVSFrame); const gridX1 = this.compWidth + 1; const gridY1 = this.compHeight + 1; const compColor = new Float32Array(gridX1 * gridY1 * 4); let offsetColor = 0; for (let j = 0; j < gridY1; j++) { for (let i = 0; i < gridX1; i++) { let x = i / this.compWidth; let y = j / this.compHeight; const col = [1, 1, 1]; for (let c = 0; c < 3; c++) { col[c] = hueBase[0 + c] * x * y + hueBase[3 + c] * (1 - x) * y + hueBase[6 + c] * x * (1 - y) + hueBase[9 + c] * (1 - x) * (1 - y); } let alpha = 1; if (blending) { x *= this.mesh_width + 1; y *= this.mesh_height + 1; x = Math.clamp(x, 0, this.mesh_width - 1); y = Math.clamp(y, 0, this.mesh_height - 1); const nx = Math.floor(x); const ny = Math.floor(y); const dx = x - nx; const dy = y - ny; const alpha00 = warpColor[(ny * (this.mesh_width + 1) + nx) * 4 + 3]; const alpha01 = warpColor[(ny * (this.mesh_width + 1) + (nx + 1)) * 4 + 3]; const alpha10 = warpColor[((ny + 1) * (this.mesh_width + 1) + nx) * 4 + 3]; const alpha11 = warpColor[((ny + 1) * (this.mesh_width + 1) + (nx + 1)) * 4 + 3]; alpha = alpha00 * (1 - dx) * (1 - dy) + alpha01 * dx * (1 - dy) + alpha10 * (1 - dx) * dy + alpha11 * dx * dy; } compColor[offsetColor + 0] = col[0]; compColor[offsetColor + 1] = col[1]; compColor[offsetColor + 2] = col[2]; compColor[offsetColor + 3] = alpha; offsetColor += 4; } } return compColor; } renderQuadTexture(blending, texture, blurTexture1, blurTexture2, blurTexture3, blurMins, blurMaxs, mdVSFrame, mdVSQs, warpColor) { const compColors = this.generateCompColors(blending, mdVSFrame, warpColor); this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.indexBuf); this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this.indices, this.gl.STATIC_DRAW); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertices, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.positionLocation, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.positionLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.compColorVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, compColors, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.compColorLocation, 4, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.compColorLocation); const wrapping = mdVSFrame.wrap !== 0 ? this.gl.REPEAT : this.gl.CLAMP_TO_EDGE; this.gl.samplerParameteri(this.mainSampler, this.gl.TEXTURE_WRAP_S, wrapping); this.gl.samplerParameteri(this.mainSampler, this.gl.TEXTURE_WRAP_T, wrapping); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(0, this.mainSampler); this.gl.uniform1i(this.textureLoc, 0); this.gl.activeTexture(this.gl.TEXTURE1); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(1, this.mainSamplerFW); this.gl.uniform1i(this.textureFWLoc, 1); this.gl.activeTexture(this.gl.TEXTURE2); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(2, this.mainSamplerFC); this.gl.uniform1i(this.textureFCLoc, 2); this.gl.activeTexture(this.gl.TEXTURE3); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(3, this.mainSamplerPW); this.gl.uniform1i(this.texturePWLoc, 3); this.gl.activeTexture(this.gl.TEXTURE4); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(4, this.mainSamplerPC); this.gl.uniform1i(this.texturePCLoc, 4); this.gl.activeTexture(this.gl.TEXTURE5); this.gl.bindTexture(this.gl.TEXTURE_2D, blurTexture1); this.gl.uniform1i(this.blurTexture1Loc, 5); this.gl.activeTexture(this.gl.TEXTURE6); this.gl.bindTexture(this.gl.TEXTURE_2D, blurTexture2); this.gl.uniform1i(this.blurTexture2Loc, 6); this.gl.activeTexture(this.gl.TEXTURE7); this.gl.bindTexture(this.gl.TEXTURE_2D, blurTexture3); this.gl.uniform1i(this.blurTexture3Loc, 7); this.gl.activeTexture(this.gl.TEXTURE8); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexLQ); this.gl.uniform1i(this.noiseLQLoc, 8); this.gl.activeTexture(this.gl.TEXTURE9); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexMQ); this.gl.uniform1i(this.noiseMQLoc, 9); this.gl.activeTexture(this.gl.TEXTURE10); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexHQ); this.gl.uniform1i(this.noiseHQLoc, 10); this.gl.activeTexture(this.gl.TEXTURE11); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexLQLite); this.gl.uniform1i(this.noiseLQLiteLoc, 11); this.gl.activeTexture(this.gl.TEXTURE12); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexLQ); this.gl.bindSampler(12, this.noise.noiseTexPointLQ); this.gl.uniform1i(this.noisePointLQLoc, 12); this.gl.activeTexture(this.gl.TEXTURE13); this.gl.bindTexture(this.gl.TEXTURE_3D, this.noise.noiseTexVolLQ); this.gl.uniform1i(this.noiseVolLQLoc, 13); this.gl.activeTexture(this.gl.TEXTURE14); this.gl.bindTexture(this.gl.TEXTURE_3D, this.noise.noiseTexVolHQ); this.gl.uniform1i(this.noiseVolHQLoc, 14); for (let i = 0; i < this.userTextures.length; i++) { const userTexture = this.userTextures[i]; this.gl.activeTexture(this.gl.TEXTURE15 + i); this.gl.bindTexture(this.gl.TEXTURE_2D, this.image.getTexture(userTexture.sampler)); this.gl.uniform1i(userTexture.textureLoc, 15 + i); } this.gl.uniform1f(this.timeLoc, mdVSFrame.time); this.gl.uniform1f(this.gammaAdjLoc, mdVSFrame.gammaadj); this.gl.uniform1f(this.echoZoomLoc, mdVSFrame.echo_zoom); this.gl.uniform1f(this.echoAlphaLoc, mdVSFrame.echo_alpha); this.gl.uniform1f(this.echoOrientationLoc, mdVSFrame.echo_orient); this.gl.uniform1i(this.invertLoc, mdVSFrame.invert); this.gl.uniform1i(this.brightenLoc, mdVSFrame.brighten); this.gl.uniform1i(this.darkenLoc, mdVSFrame.darken); this.gl.uniform1i(this.solarizeLoc, mdVSFrame.solarize); this.gl.uniform2fv(this.resolutionLoc, [this.texsizeX, this.texsizeY]); this.gl.uniform4fv(this.aspectLoc, [this.aspectx, this.aspecty, this.invAspectx, this.invAspecty]); this.gl.uniform4fv(this.texsizeLoc, new Float32Array([this.texsizeX, this.texsizeY, 1.0 / this.texsizeX, 1.0 / this.texsizeY])); this.gl.uniform4fv(this.texsizeNoiseLQLoc, [256, 256, 1 / 256, 1 / 256]); this.gl.uniform4fv(this.texsizeNoiseMQLoc, [256, 256, 1 / 256, 1 / 256]); this.gl.uniform4fv(this.texsizeNoiseHQLoc, [256, 256, 1 / 256, 1 / 256]); this.gl.uniform4fv(this.texsizeNoiseLQLiteLoc, [32, 32, 1 / 32, 1 / 32]); this.gl.uniform4fv(this.texsizeNoiseVolLQLoc, [32, 32, 1 / 32, 1 / 32]); this.gl.uniform4fv(this.texsizeNoiseVolHQLoc, [32, 32, 1 / 32, 1 / 32]); this.gl.uniform1f(this.bassLoc, mdVSFrame.bass); this.gl.uniform1f(this.midLoc, mdVSFrame.mid); this.gl.uniform1f(this.trebLoc, mdVSFrame.treb); this.gl.uniform1f(this.volLoc, (mdVSFrame.bass + mdVSFrame.mid + mdVSFrame.treb) / 3); this.gl.uniform1f(this.bassAttLoc, mdVSFrame.bass_att); this.gl.uniform1f(this.midAttLoc, mdVSFrame.mid_att); this.gl.uniform1f(this.trebAttLoc, mdVSFrame.treb_att); this.gl.uniform1f(this.volAttLoc, (mdVSFrame.bass_att + mdVSFrame.mid_att + mdVSFrame.treb_att) / 3); this.gl.uniform1f(this.frameLoc, mdVSFrame.frame); this.gl.uniform1f(this.fpsLoc, mdVSFrame.fps); this.gl.uniform4fv(this.randPresetLoc, mdVSFrame.rand_preset); this.gl.uniform4fv(this.randFrameLoc, new Float32Array([Math.random(), Math.random(), Math.random(), Math.random()])); this.gl.uniform1f(this.fShaderLoc, mdVSFrame.fshader); this.gl.uniform4fv(this.qaLoc, new Float32Array([mdVSQs.q1 || 0, mdVSQs.q2 || 0, mdVSQs.q3 || 0, mdVSQs.q4 || 0])); this.gl.uniform4fv(this.qbLoc, new Float32Array([mdVSQs.q5 || 0, mdVSQs.q6 || 0, mdVSQs.q7 || 0, mdVSQs.q8 || 0])); this.gl.uniform4fv(this.qcLoc, new Float32Array([mdVSQs.q9 || 0, mdVSQs.q10 || 0, mdVSQs.q11 || 0, mdVSQs.q12 || 0])); this.gl.uniform4fv(this.qdLoc, new Float32Array([mdVSQs.q13 || 0, mdVSQs.q14 || 0, mdVSQs.q15 || 0, mdVSQs.q16 || 0])); this.gl.uniform4fv(this.qeLoc, new Float32Array([mdVSQs.q17 || 0, mdVSQs.q18 || 0, mdVSQs.q19 || 0, mdVSQs.q20 || 0])); this.gl.uniform4fv(this.qfLoc, new Float32Array([mdVSQs.q21 || 0, mdVSQs.q22 || 0, mdVSQs.q23 || 0, mdVSQs.q24 || 0])); this.gl.uniform4fv(this.qgLoc, new Float32Array([mdVSQs.q25 || 0, mdVSQs.q26 || 0, mdVSQs.q27 || 0, mdVSQs.q28 || 0])); this.gl.uniform4fv(this.qhLoc, new Float32Array([mdVSQs.q29 || 0, mdVSQs.q30 || 0, mdVSQs.q31 || 0, mdVSQs.q32 || 0])); this.gl.uniform4fv(this.slowRoamCosLoc, [0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.005), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.008), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.013), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.022)]); this.gl.uniform4fv(this.roamCosLoc, [0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.3), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 1.3), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 5.0), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 20.0)]); this.gl.uniform4fv(this.slowRoamSinLoc, [0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.005), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.008), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.013), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.022)]); this.gl.uniform4fv(this.roamSinLoc, [0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.3), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 1.3), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 5.0), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 20.0)]); this.bindBlurVals(blurMins, blurMaxs); if (blending) { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); } else { this.gl.disable(this.gl.BLEND); } this.gl.drawElements(this.gl.TRIANGLES, this.indices.length, this.gl.UNSIGNED_SHORT, 0); if (!blending) { this.gl.enable(this.gl.BLEND); } } } /***/ }), /***/ "./src/rendering/shaders/output.js": /*!*****************************************!*\ !*** ./src/rendering/shaders/output.js ***! \*****************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return OutputShader; }); /* harmony import */ var _shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class OutputShader { constructor(gl, opts) { this.gl = gl; this.textureRatio = opts.textureRatio; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); this.vertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); if (this.useFXAA()) { this.createFXAAShader(); } else { this.createShader(); } } useFXAA() { return this.textureRatio <= 1; } updateGlobals(opts) { this.textureRatio = opts.textureRatio; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.gl.deleteProgram(this.shaderProgram); if (this.useFXAA()) { this.createFXAAShader(); } else { this.createShader(); } } // based on https://github.com/mattdesl/glsl-fxaa createFXAAShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, `#version 300 es const vec2 halfmad = vec2(0.5); in vec2 aPos; out vec2 v_rgbM; out vec2 v_rgbNW; out vec2 v_rgbNE; out vec2 v_rgbSW; out vec2 v_rgbSE; uniform vec4 texsize; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); v_rgbM = aPos * halfmad + halfmad; v_rgbNW = v_rgbM + (vec2(-1.0, -1.0) * texsize.zx); v_rgbNE = v_rgbM + (vec2(1.0, -1.0) * texsize.zx); v_rgbSW = v_rgbM + (vec2(-1.0, 1.0) * texsize.zx); v_rgbSE = v_rgbM + (vec2(1.0, 1.0) * texsize.zx); }`); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, `#version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec2 v_rgbM; in vec2 v_rgbNW; in vec2 v_rgbNE; in vec2 v_rgbSW; in vec2 v_rgbSE; out vec4 fragColor; uniform vec4 texsize; uniform sampler2D uTexture; #ifndef FXAA_REDUCE_MIN #define FXAA_REDUCE_MIN (1.0/ 128.0) #endif #ifndef FXAA_REDUCE_MUL #define FXAA_REDUCE_MUL (1.0 / 8.0) #endif #ifndef FXAA_SPAN_MAX #define FXAA_SPAN_MAX 8.0 #endif void main(void) { vec4 color; vec3 rgbNW = textureLod(uTexture, v_rgbNW, 0.0).xyz; vec3 rgbNE = textureLod(uTexture, v_rgbNE, 0.0).xyz; vec3 rgbSW = textureLod(uTexture, v_rgbSW, 0.0).xyz; vec3 rgbSE = textureLod(uTexture, v_rgbSE, 0.0).xyz; vec3 rgbM = textureLod(uTexture, v_rgbM, 0.0).xyz; vec3 luma = vec3(0.299, 0.587, 0.114); float lumaNW = dot(rgbNW, luma); float lumaNE = dot(rgbNE, luma); float lumaSW = dot(rgbSW, luma); float lumaSE = dot(rgbSE, luma); float lumaM = dot(rgbM, luma); float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); mediump vec2 dir; dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texsize.zw; vec3 rgbA = 0.5 * ( textureLod(uTexture, v_rgbM + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(uTexture, v_rgbM + dir * (2.0 / 3.0 - 0.5), 0.0).xyz); vec3 rgbB = rgbA * 0.5 + 0.25 * ( textureLod(uTexture, v_rgbM + dir * -0.5, 0.0).xyz + textureLod(uTexture, v_rgbM + dir * 0.5, 0.0).xyz); float lumaB = dot(rgbB, luma); if ((lumaB < lumaMin) || (lumaB > lumaMax)) color = vec4(rgbA, 1.0); else color = vec4(rgbB, 1.0); fragColor = color; }`); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "uTexture"); this.texsizeLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize"); } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, `#version 300 es const vec2 halfmad = vec2(0.5); in vec2 aPos; out vec2 uv; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); uv = aPos * halfmad + halfmad; }`); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, `#version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec2 uv; out vec4 fragColor; uniform sampler2D uTexture; void main(void) { fragColor = vec4(texture(uTexture, uv).rgb, 1.0); }`); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "uTexture"); } renderQuadTexture(texture) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.positionLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.positionLocation); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.uniform1i(this.textureLoc, 0); if (this.useFXAA()) { this.gl.uniform4fv(this.texsizeLoc, new Float32Array([this.texsizeX, this.texsizeY, 1.0 / this.texsizeX, 1.0 / this.texsizeY])); } this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4); } } /***/ }), /***/ "./src/rendering/shaders/resample.js": /*!*******************************************!*\ !*** ./src/rendering/shaders/resample.js ***! \*******************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ResampleShader; }); /* harmony import */ var _shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class ResampleShader { constructor(gl) { this.gl = gl; this.positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); this.vertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, `#version 300 es const vec2 halfmad = vec2(0.5); in vec2 aPos; out vec2 uv; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); uv = aPos * halfmad + halfmad; }`); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, `#version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec2 uv; out vec4 fragColor; uniform sampler2D uTexture; void main(void) { fragColor = vec4(texture(uTexture, uv).rgb, 1.0); }`); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "uTexture"); } renderQuadTexture(texture) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.positionLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.positionLocation); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.gl.uniform1i(this.textureLoc, 0); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4); } } /***/ }), /***/ "./src/rendering/shaders/shaderUtils.js": /*!**********************************************!*\ !*** ./src/rendering/shaders/shaderUtils.js ***! \**********************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ShaderUtils; }); const lineMatcher = /uniform sampler2D sampler_(?:.+?);/g; const samplerMatcher = /uniform sampler2D sampler_(.+?);/; class ShaderUtils { static getShaderParts(t) { const sbIndex = t.indexOf("shader_body"); if (t && sbIndex > -1) { const beforeShaderBody = t.substring(0, sbIndex); const afterShaderBody = t.substring(sbIndex); const firstCurly = afterShaderBody.indexOf("{"); const lastCurly = afterShaderBody.lastIndexOf("}"); const shaderBody = afterShaderBody.substring(firstCurly + 1, lastCurly); return [beforeShaderBody, shaderBody]; } return ["", t]; } static getFragmentFloatPrecision(gl) { if (gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) { return "highp"; } else if (gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) { return "mediump"; } return "lowp"; } static getUserSamplers(text) { const samplers = []; const lineMatches = text.match(lineMatcher); if (lineMatches && lineMatches.length > 0) { for (let i = 0; i < lineMatches.length; i++) { const samplerMatches = lineMatches[i].match(samplerMatcher); if (samplerMatches && samplerMatches.length > 0) { const sampler = samplerMatches[1]; samplers.push({ sampler }); } } } return samplers; } } /***/ }), /***/ "./src/rendering/shaders/warp.js": /*!***************************************!*\ !*** ./src/rendering/shaders/warp.js ***! \***************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return WarpShader; }); /* harmony import */ var _shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class WarpShader { constructor(gl, noise, image, opts = {}) { this.gl = gl; this.noise = noise; this.image = image; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.buildPositions(); this.indexBuf = gl.createBuffer(); this.positionVertexBuf = this.gl.createBuffer(); this.warpUvVertexBuf = this.gl.createBuffer(); this.warpColorVertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); this.mainSampler = this.gl.createSampler(); this.mainSamplerFW = this.gl.createSampler(); this.mainSamplerFC = this.gl.createSampler(); this.mainSamplerPW = this.gl.createSampler(); this.mainSamplerPC = this.gl.createSampler(); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.mainSamplerFW, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.samplerParameteri(this.mainSamplerFC, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.mainSamplerPW, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.samplerParameteri(this.mainSamplerPC, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); } // based on https://github.com/mrdoob/three.js/blob/master/src/geometries/PlaneGeometry.js buildPositions() { const width = 2; const height = 2; const widthHalf = width / 2; const heightHalf = height / 2; const gridX = this.mesh_width; const gridY = this.mesh_height; const gridX1 = gridX + 1; const gridY1 = gridY + 1; const segmentWidth = width / gridX; const segmentHeight = height / gridY; const vertices = []; for (let iy = 0; iy < gridY1; iy++) { const y = iy * segmentHeight - heightHalf; for (let ix = 0; ix < gridX1; ix++) { const x = ix * segmentWidth - widthHalf; vertices.push(x, -y, 0); } } const indices = []; for (let iy = 0; iy < gridY; iy++) { for (let ix = 0; ix < gridX; ix++) { const a = ix + gridX1 * iy; const b = ix + gridX1 * (iy + 1); const c = ix + 1 + gridX1 * (iy + 1); const d = ix + 1 + gridX1 * iy; indices.push(a, b, d); indices.push(b, c, d); } } this.vertices = new Float32Array(vertices); this.indices = new Uint16Array(indices); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.buildPositions(); } createShader(shaderText = "") { let fragShaderText; let fragShaderHeaderText; if (shaderText.length === 0) { fragShaderText = "ret = texture(sampler_main, uv).rgb * decay;"; fragShaderHeaderText = ""; } else { const shaderParts = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getShaderParts(shaderText); fragShaderHeaderText = shaderParts[0]; fragShaderText = shaderParts[1]; } fragShaderText = fragShaderText.replace(/texture2D/g, "texture"); fragShaderText = fragShaderText.replace(/texture3D/g, "texture"); this.userTextures = _shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getUserSamplers(fragShaderHeaderText); this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es precision ${this.floatPrecision} float; const vec2 halfmad = vec2(0.5); in vec2 aPos; in vec2 aWarpUv; in vec4 aWarpColor; out vec2 uv; out vec2 uv_orig; out vec4 vColor; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); uv_orig = aPos * halfmad + halfmad; uv = aWarpUv; vColor = aWarpColor; } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; precision mediump sampler3D; in vec2 uv; in vec2 uv_orig; in vec4 vColor; out vec4 fragColor; uniform sampler2D sampler_main; uniform sampler2D sampler_fw_main; uniform sampler2D sampler_fc_main; uniform sampler2D sampler_pw_main; uniform sampler2D sampler_pc_main; uniform sampler2D sampler_blur1; uniform sampler2D sampler_blur2; uniform sampler2D sampler_blur3; uniform sampler2D sampler_noise_lq; uniform sampler2D sampler_noise_lq_lite; uniform sampler2D sampler_noise_mq; uniform sampler2D sampler_noise_hq; uniform sampler2D sampler_pw_noise_lq; uniform sampler3D sampler_noisevol_lq; uniform sampler3D sampler_noisevol_hq; uniform float time; uniform float decay; uniform vec2 resolution; uniform vec4 aspect; uniform vec4 texsize; uniform vec4 texsize_noise_lq; uniform vec4 texsize_noise_mq; uniform vec4 texsize_noise_hq; uniform vec4 texsize_noise_lq_lite; uniform vec4 texsize_noisevol_lq; uniform vec4 texsize_noisevol_hq; uniform float bass; uniform float mid; uniform float treb; uniform float vol; uniform float bass_att; uniform float mid_att; uniform float treb_att; uniform float vol_att; uniform float frame; uniform float fps; uniform vec4 _qa; uniform vec4 _qb; uniform vec4 _qc; uniform vec4 _qd; uniform vec4 _qe; uniform vec4 _qf; uniform vec4 _qg; uniform vec4 _qh; #define q1 _qa.x #define q2 _qa.y #define q3 _qa.z #define q4 _qa.w #define q5 _qb.x #define q6 _qb.y #define q7 _qb.z #define q8 _qb.w #define q9 _qc.x #define q10 _qc.y #define q11 _qc.z #define q12 _qc.w #define q13 _qd.x #define q14 _qd.y #define q15 _qd.z #define q16 _qd.w #define q17 _qe.x #define q18 _qe.y #define q19 _qe.z #define q20 _qe.w #define q21 _qf.x #define q22 _qf.y #define q23 _qf.z #define q24 _qf.w #define q25 _qg.x #define q26 _qg.y #define q27 _qg.z #define q28 _qg.w #define q29 _qh.x #define q30 _qh.y #define q31 _qh.z #define q32 _qh.w uniform vec4 slow_roam_cos; uniform vec4 roam_cos; uniform vec4 slow_roam_sin; uniform vec4 roam_sin; uniform float blur1_min; uniform float blur1_max; uniform float blur2_min; uniform float blur2_max; uniform float blur3_min; uniform float blur3_max; uniform float scale1; uniform float scale2; uniform float scale3; uniform float bias1; uniform float bias2; uniform float bias3; uniform vec4 rand_frame; uniform vec4 rand_preset; float PI = ${Math.PI}; ${fragShaderHeaderText} void main(void) { vec3 ret; float rad = length(uv_orig - 0.5); float ang = atan(uv_orig.x - 0.5, uv_orig.y - 0.5); ${fragShaderText} fragColor = vec4(ret, 1.0) * vColor; } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.warpUvLocation = this.gl.getAttribLocation(this.shaderProgram, "aWarpUv"); this.warpColorLocation = this.gl.getAttribLocation(this.shaderProgram, "aWarpColor"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_main"); this.textureFWLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_fw_main"); this.textureFCLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_fc_main"); this.texturePWLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_pw_main"); this.texturePCLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_pc_main"); this.blurTexture1Loc = this.gl.getUniformLocation(this.shaderProgram, "sampler_blur1"); this.blurTexture2Loc = this.gl.getUniformLocation(this.shaderProgram, "sampler_blur2"); this.blurTexture3Loc = this.gl.getUniformLocation(this.shaderProgram, "sampler_blur3"); this.noiseLQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_lq"); this.noiseMQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_mq"); this.noiseHQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_hq"); this.noiseLQLiteLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noise_lq_lite"); this.noisePointLQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_pw_noise_lq"); this.noiseVolLQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noisevol_lq"); this.noiseVolHQLoc = this.gl.getUniformLocation(this.shaderProgram, "sampler_noisevol_hq"); this.decayLoc = this.gl.getUniformLocation(this.shaderProgram, "decay"); this.texsizeLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize"); this.texsizeNoiseLQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_lq"); this.texsizeNoiseMQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_mq"); this.texsizeNoiseHQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_hq"); this.texsizeNoiseLQLiteLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noise_lq_lite"); this.texsizeNoiseVolLQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noisevol_lq"); this.texsizeNoiseVolHQLoc = this.gl.getUniformLocation(this.shaderProgram, "texsize_noisevol_hq"); this.resolutionLoc = this.gl.getUniformLocation(this.shaderProgram, "resolution"); this.aspectLoc = this.gl.getUniformLocation(this.shaderProgram, "aspect"); this.bassLoc = this.gl.getUniformLocation(this.shaderProgram, "bass"); this.midLoc = this.gl.getUniformLocation(this.shaderProgram, "mid"); this.trebLoc = this.gl.getUniformLocation(this.shaderProgram, "treb"); this.volLoc = this.gl.getUniformLocation(this.shaderProgram, "vol"); this.bassAttLoc = this.gl.getUniformLocation(this.shaderProgram, "bass_att"); this.midAttLoc = this.gl.getUniformLocation(this.shaderProgram, "mid_att"); this.trebAttLoc = this.gl.getUniformLocation(this.shaderProgram, "treb_att"); this.volAttLoc = this.gl.getUniformLocation(this.shaderProgram, "vol_att"); this.timeLoc = this.gl.getUniformLocation(this.shaderProgram, "time"); this.frameLoc = this.gl.getUniformLocation(this.shaderProgram, "frame"); this.fpsLoc = this.gl.getUniformLocation(this.shaderProgram, "fps"); this.blur1MinLoc = this.gl.getUniformLocation(this.shaderProgram, "blur1_min"); this.blur1MaxLoc = this.gl.getUniformLocation(this.shaderProgram, "blur1_max"); this.blur2MinLoc = this.gl.getUniformLocation(this.shaderProgram, "blur2_min"); this.blur2MaxLoc = this.gl.getUniformLocation(this.shaderProgram, "blur2_max"); this.blur3MinLoc = this.gl.getUniformLocation(this.shaderProgram, "blur3_min"); this.blur3MaxLoc = this.gl.getUniformLocation(this.shaderProgram, "blur3_max"); this.scale1Loc = this.gl.getUniformLocation(this.shaderProgram, "scale1"); this.scale2Loc = this.gl.getUniformLocation(this.shaderProgram, "scale2"); this.scale3Loc = this.gl.getUniformLocation(this.shaderProgram, "scale3"); this.bias1Loc = this.gl.getUniformLocation(this.shaderProgram, "bias1"); this.bias2Loc = this.gl.getUniformLocation(this.shaderProgram, "bias2"); this.bias3Loc = this.gl.getUniformLocation(this.shaderProgram, "bias3"); this.randPresetLoc = this.gl.getUniformLocation(this.shaderProgram, "rand_preset"); this.randFrameLoc = this.gl.getUniformLocation(this.shaderProgram, "rand_frame"); this.qaLoc = this.gl.getUniformLocation(this.shaderProgram, "_qa"); this.qbLoc = this.gl.getUniformLocation(this.shaderProgram, "_qb"); this.qcLoc = this.gl.getUniformLocation(this.shaderProgram, "_qc"); this.qdLoc = this.gl.getUniformLocation(this.shaderProgram, "_qd"); this.qeLoc = this.gl.getUniformLocation(this.shaderProgram, "_qe"); this.qfLoc = this.gl.getUniformLocation(this.shaderProgram, "_qf"); this.qgLoc = this.gl.getUniformLocation(this.shaderProgram, "_qg"); this.qhLoc = this.gl.getUniformLocation(this.shaderProgram, "_qh"); this.slowRoamCosLoc = this.gl.getUniformLocation(this.shaderProgram, "slow_roam_cos"); this.roamCosLoc = this.gl.getUniformLocation(this.shaderProgram, "roam_cos"); this.slowRoamSinLoc = this.gl.getUniformLocation(this.shaderProgram, "slow_roam_sin"); this.roamSinLoc = this.gl.getUniformLocation(this.shaderProgram, "roam_sin"); for (let i = 0; i < this.userTextures.length; i++) { const userTexture = this.userTextures[i]; userTexture.textureLoc = this.gl.getUniformLocation(this.shaderProgram, `sampler_${userTexture.sampler}`); } } updateShader(shaderText) { this.createShader(shaderText); } bindBlurVals(blurMins, blurMaxs) { const blurMin1 = blurMins[0]; const blurMin2 = blurMins[1]; const blurMin3 = blurMins[2]; const blurMax1 = blurMaxs[0]; const blurMax2 = blurMaxs[1]; const blurMax3 = blurMaxs[2]; const scale1 = blurMax1 - blurMin1; const bias1 = blurMin1; const scale2 = blurMax2 - blurMin2; const bias2 = blurMin2; const scale3 = blurMax3 - blurMin3; const bias3 = blurMin3; this.gl.uniform1f(this.blur1MinLoc, blurMin1); this.gl.uniform1f(this.blur1MaxLoc, blurMax1); this.gl.uniform1f(this.blur2MinLoc, blurMin2); this.gl.uniform1f(this.blur2MaxLoc, blurMax2); this.gl.uniform1f(this.blur3MinLoc, blurMin3); this.gl.uniform1f(this.blur3MaxLoc, blurMax3); this.gl.uniform1f(this.scale1Loc, scale1); this.gl.uniform1f(this.scale2Loc, scale2); this.gl.uniform1f(this.scale3Loc, scale3); this.gl.uniform1f(this.bias1Loc, bias1); this.gl.uniform1f(this.bias2Loc, bias2); this.gl.uniform1f(this.bias3Loc, bias3); } renderQuadTexture(blending, texture, blurTexture1, blurTexture2, blurTexture3, blurMins, blurMaxs, mdVSFrame, mdVSQs, warpUVs, warpColor) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.indexBuf); this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this.indices, this.gl.STATIC_DRAW); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertices, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.positionLocation, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.positionLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.warpUvVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, warpUVs, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.warpUvLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.warpUvLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.warpColorVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, warpColor, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.warpColorLocation, 4, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.warpColorLocation); const wrapping = mdVSFrame.wrap !== 0 ? this.gl.REPEAT : this.gl.CLAMP_TO_EDGE; this.gl.samplerParameteri(this.mainSampler, this.gl.TEXTURE_WRAP_S, wrapping); this.gl.samplerParameteri(this.mainSampler, this.gl.TEXTURE_WRAP_T, wrapping); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(0, this.mainSampler); this.gl.uniform1i(this.textureLoc, 0); this.gl.activeTexture(this.gl.TEXTURE1); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(1, this.mainSamplerFW); this.gl.uniform1i(this.textureFWLoc, 1); this.gl.activeTexture(this.gl.TEXTURE2); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(2, this.mainSamplerFC); this.gl.uniform1i(this.textureFCLoc, 2); this.gl.activeTexture(this.gl.TEXTURE3); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(3, this.mainSamplerPW); this.gl.uniform1i(this.texturePWLoc, 3); this.gl.activeTexture(this.gl.TEXTURE4); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); this.gl.bindSampler(4, this.mainSamplerPC); this.gl.uniform1i(this.texturePCLoc, 4); this.gl.activeTexture(this.gl.TEXTURE5); this.gl.bindTexture(this.gl.TEXTURE_2D, blurTexture1); this.gl.uniform1i(this.blurTexture1Loc, 5); this.gl.activeTexture(this.gl.TEXTURE6); this.gl.bindTexture(this.gl.TEXTURE_2D, blurTexture2); this.gl.uniform1i(this.blurTexture2Loc, 6); this.gl.activeTexture(this.gl.TEXTURE7); this.gl.bindTexture(this.gl.TEXTURE_2D, blurTexture3); this.gl.uniform1i(this.blurTexture3Loc, 7); this.gl.activeTexture(this.gl.TEXTURE8); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexLQ); this.gl.uniform1i(this.noiseLQLoc, 8); this.gl.activeTexture(this.gl.TEXTURE9); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexMQ); this.gl.uniform1i(this.noiseMQLoc, 9); this.gl.activeTexture(this.gl.TEXTURE10); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexHQ); this.gl.uniform1i(this.noiseHQLoc, 10); this.gl.activeTexture(this.gl.TEXTURE11); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexLQLite); this.gl.uniform1i(this.noiseLQLiteLoc, 11); this.gl.activeTexture(this.gl.TEXTURE12); this.gl.bindTexture(this.gl.TEXTURE_2D, this.noise.noiseTexLQ); this.gl.bindSampler(12, this.noise.noiseTexPointLQ); this.gl.uniform1i(this.noisePointLQLoc, 12); this.gl.activeTexture(this.gl.TEXTURE13); this.gl.bindTexture(this.gl.TEXTURE_3D, this.noise.noiseTexVolLQ); this.gl.uniform1i(this.noiseVolLQLoc, 13); this.gl.activeTexture(this.gl.TEXTURE14); this.gl.bindTexture(this.gl.TEXTURE_3D, this.noise.noiseTexVolHQ); this.gl.uniform1i(this.noiseVolHQLoc, 14); for (let i = 0; i < this.userTextures.length; i++) { const userTexture = this.userTextures[i]; this.gl.activeTexture(this.gl.TEXTURE15 + i); this.gl.bindTexture(this.gl.TEXTURE_2D, this.image.getTexture(userTexture.sampler)); this.gl.uniform1i(userTexture.textureLoc, 15 + i); } this.gl.uniform1f(this.decayLoc, mdVSFrame.decay); this.gl.uniform2fv(this.resolutionLoc, [this.texsizeX, this.texsizeY]); this.gl.uniform4fv(this.aspectLoc, [this.aspectx, this.aspecty, this.invAspectx, this.invAspecty]); this.gl.uniform4fv(this.texsizeLoc, [this.texsizeX, this.texsizeY, 1.0 / this.texsizeX, 1.0 / this.texsizeY]); this.gl.uniform4fv(this.texsizeNoiseLQLoc, [256, 256, 1 / 256, 1 / 256]); this.gl.uniform4fv(this.texsizeNoiseMQLoc, [256, 256, 1 / 256, 1 / 256]); this.gl.uniform4fv(this.texsizeNoiseHQLoc, [256, 256, 1 / 256, 1 / 256]); this.gl.uniform4fv(this.texsizeNoiseLQLiteLoc, [32, 32, 1 / 32, 1 / 32]); this.gl.uniform4fv(this.texsizeNoiseVolLQLoc, [32, 32, 1 / 32, 1 / 32]); this.gl.uniform4fv(this.texsizeNoiseVolHQLoc, [32, 32, 1 / 32, 1 / 32]); this.gl.uniform1f(this.bassLoc, mdVSFrame.bass); this.gl.uniform1f(this.midLoc, mdVSFrame.mid); this.gl.uniform1f(this.trebLoc, mdVSFrame.treb); this.gl.uniform1f(this.volLoc, (mdVSFrame.bass + mdVSFrame.mid + mdVSFrame.treb) / 3); this.gl.uniform1f(this.bassAttLoc, mdVSFrame.bass_att); this.gl.uniform1f(this.midAttLoc, mdVSFrame.mid_att); this.gl.uniform1f(this.trebAttLoc, mdVSFrame.treb_att); this.gl.uniform1f(this.volAttLoc, (mdVSFrame.bass_att + mdVSFrame.mid_att + mdVSFrame.treb_att) / 3); this.gl.uniform1f(this.timeLoc, mdVSFrame.time); this.gl.uniform1f(this.frameLoc, mdVSFrame.frame); this.gl.uniform1f(this.fpsLoc, mdVSFrame.fps); this.gl.uniform4fv(this.randPresetLoc, mdVSFrame.rand_preset); this.gl.uniform4fv(this.randFrameLoc, new Float32Array([Math.random(), Math.random(), Math.random(), Math.random()])); this.gl.uniform4fv(this.qaLoc, new Float32Array([mdVSQs.q1 || 0, mdVSQs.q2 || 0, mdVSQs.q3 || 0, mdVSQs.q4 || 0])); this.gl.uniform4fv(this.qbLoc, new Float32Array([mdVSQs.q5 || 0, mdVSQs.q6 || 0, mdVSQs.q7 || 0, mdVSQs.q8 || 0])); this.gl.uniform4fv(this.qcLoc, new Float32Array([mdVSQs.q9 || 0, mdVSQs.q10 || 0, mdVSQs.q11 || 0, mdVSQs.q12 || 0])); this.gl.uniform4fv(this.qdLoc, new Float32Array([mdVSQs.q13 || 0, mdVSQs.q14 || 0, mdVSQs.q15 || 0, mdVSQs.q16 || 0])); this.gl.uniform4fv(this.qeLoc, new Float32Array([mdVSQs.q17 || 0, mdVSQs.q18 || 0, mdVSQs.q19 || 0, mdVSQs.q20 || 0])); this.gl.uniform4fv(this.qfLoc, new Float32Array([mdVSQs.q21 || 0, mdVSQs.q22 || 0, mdVSQs.q23 || 0, mdVSQs.q24 || 0])); this.gl.uniform4fv(this.qgLoc, new Float32Array([mdVSQs.q25 || 0, mdVSQs.q26 || 0, mdVSQs.q27 || 0, mdVSQs.q28 || 0])); this.gl.uniform4fv(this.qhLoc, new Float32Array([mdVSQs.q29 || 0, mdVSQs.q30 || 0, mdVSQs.q31 || 0, mdVSQs.q32 || 0])); this.gl.uniform4fv(this.slowRoamCosLoc, [0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.005), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.008), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.013), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.022)]); this.gl.uniform4fv(this.roamCosLoc, [0.5 + 0.5 * Math.cos(mdVSFrame.time * 0.3), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 1.3), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 5.0), 0.5 + 0.5 * Math.cos(mdVSFrame.time * 20.0)]); this.gl.uniform4fv(this.slowRoamSinLoc, [0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.005), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.008), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.013), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.022)]); this.gl.uniform4fv(this.roamSinLoc, [0.5 + 0.5 * Math.sin(mdVSFrame.time * 0.3), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 1.3), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 5.0), 0.5 + 0.5 * Math.sin(mdVSFrame.time * 20.0)]); this.bindBlurVals(blurMins, blurMaxs); if (blending) { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); } else { this.gl.disable(this.gl.BLEND); } this.gl.drawElements(this.gl.TRIANGLES, this.indices.length, this.gl.UNSIGNED_SHORT, 0); if (!blending) { this.gl.enable(this.gl.BLEND); } } } /***/ }), /***/ "./src/rendering/shapes/customShape.js": /*!*********************************************!*\ !*** ./src/rendering/shapes/customShape.js ***! \*********************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return CustomShape; }); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils */ "./src/utils.js"); /* harmony import */ var _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../shaders/shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class CustomShape { constructor(index, gl, opts) { this.index = index; this.gl = gl; const maxSides = 101; this.positions = new Float32Array((maxSides + 2) * 3); this.colors = new Float32Array((maxSides + 2) * 4); this.uvs = new Float32Array((maxSides + 2) * 2); this.borderPositions = new Float32Array((maxSides + 1) * 3); this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.positionVertexBuf = this.gl.createBuffer(); this.colorVertexBuf = this.gl.createBuffer(); this.uvVertexBuf = this.gl.createBuffer(); this.borderPositionVertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_1__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); this.createBorderShader(); this.mainSampler = this.gl.createSampler(); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.samplerParameteri(this.mainSampler, gl.TEXTURE_WRAP_T, gl.REPEAT); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es in vec3 aPos; in vec4 aColor; in vec2 aUv; out vec4 vColor; out vec2 vUv; void main(void) { vColor = aColor; vUv = aUv; gl_Position = vec4(aPos, 1.0); } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; uniform sampler2D uTexture; uniform float uTextured; in vec4 vColor; in vec2 vUv; out vec4 fragColor; void main(void) { if (uTextured != 0.0) { fragColor = texture(uTexture, vUv) * vColor; } else { fragColor = vColor; } } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.aPosLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.aColorLocation = this.gl.getAttribLocation(this.shaderProgram, "aColor"); this.aUvLocation = this.gl.getAttribLocation(this.shaderProgram, "aUv"); this.texturedLoc = this.gl.getUniformLocation(this.shaderProgram, "uTextured"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "uTexture"); } createBorderShader() { this.borderShaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es in vec3 aBorderPos; uniform vec2 thickOffset; void main(void) { gl_Position = vec4(aBorderPos + vec3(thickOffset, 0.0), 1.0); } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; out vec4 fragColor; uniform vec4 uBorderColor; void main(void) { fragColor = uBorderColor; } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.borderShaderProgram, vertShader); this.gl.attachShader(this.borderShaderProgram, fragShader); this.gl.linkProgram(this.borderShaderProgram); this.aBorderPosLoc = this.gl.getAttribLocation(this.borderShaderProgram, "aBorderPos"); this.uBorderColorLoc = this.gl.getUniformLocation(this.borderShaderProgram, "uBorderColor"); this.thickOffsetLoc = this.gl.getUniformLocation(this.shaderProgram, "thickOffset"); } drawCustomShape(blendProgress, globalVars, presetEquationRunner, shapeEqs, prevTexture) { if (shapeEqs.baseVals.enabled !== 0) { if (!presetEquationRunner.preset.useWASM) { this.setupShapeBuffers(presetEquationRunner.mdVSFrame.wrap); let mdVSShape = Object.assign({}, presetEquationRunner.mdVSShapes[this.index], presetEquationRunner.mdVSFrameMapShapes[this.index], globalVars); // If we aren't setting these every instance, set them initially if (presetEquationRunner.preset.shapes[this.index].frame_eqs_str === "") { mdVSShape = Object.assign(mdVSShape, presetEquationRunner.mdVSQAfterFrame, presetEquationRunner.mdVSTShapeInits[this.index]); } const baseVals = presetEquationRunner.preset.shapes[this.index].baseVals; const numInst = Math.clamp(baseVals.num_inst, 1, 1024); for (let j = 0; j < numInst; j++) { mdVSShape.instance = j; mdVSShape.x = baseVals.x; mdVSShape.y = baseVals.y; mdVSShape.rad = baseVals.rad; mdVSShape.ang = baseVals.ang; mdVSShape.r = baseVals.r; mdVSShape.g = baseVals.g; mdVSShape.b = baseVals.b; mdVSShape.a = baseVals.a; mdVSShape.r2 = baseVals.r2; mdVSShape.g2 = baseVals.g2; mdVSShape.b2 = baseVals.b2; mdVSShape.a2 = baseVals.a2; mdVSShape.border_r = baseVals.border_r; mdVSShape.border_g = baseVals.border_g; mdVSShape.border_b = baseVals.border_b; mdVSShape.border_a = baseVals.border_a; mdVSShape.thickoutline = baseVals.thickoutline; mdVSShape.textured = baseVals.textured; mdVSShape.tex_zoom = baseVals.tex_zoom; mdVSShape.tex_ang = baseVals.tex_ang; mdVSShape.additive = baseVals.additive; let mdVSShapeFrame; if (presetEquationRunner.preset.shapes[this.index].frame_eqs_str !== "") { mdVSShape = Object.assign(mdVSShape, presetEquationRunner.mdVSQAfterFrame, presetEquationRunner.mdVSTShapeInits[this.index]); mdVSShapeFrame = presetEquationRunner.runShapeFrameEquations(this.index, mdVSShape); } else { mdVSShapeFrame = mdVSShape; } let sides = mdVSShapeFrame.sides; sides = Math.clamp(sides, 3, 100); sides = Math.floor(sides); const rad = mdVSShapeFrame.rad; const ang = mdVSShapeFrame.ang; const x = mdVSShapeFrame.x * 2 - 1; const y = mdVSShapeFrame.y * -2 + 1; const r = mdVSShapeFrame.r; const g = mdVSShapeFrame.g; const b = mdVSShapeFrame.b; const a = mdVSShapeFrame.a; const r2 = mdVSShapeFrame.r2; const g2 = mdVSShapeFrame.g2; const b2 = mdVSShapeFrame.b2; const a2 = mdVSShapeFrame.a2; const borderR = mdVSShapeFrame.border_r; const borderG = mdVSShapeFrame.border_g; const borderB = mdVSShapeFrame.border_b; const borderA = mdVSShapeFrame.border_a; this.borderColor = [borderR, borderG, borderB, borderA * blendProgress]; const thickoutline = mdVSShapeFrame.thickoutline; const textured = mdVSShapeFrame.textured; const texZoom = mdVSShapeFrame.tex_zoom; const texAng = mdVSShapeFrame.tex_ang; const additive = mdVSShapeFrame.additive; const hasBorder = this.borderColor[3] > 0; const isTextured = Math.abs(textured) >= 1; const isBorderThick = Math.abs(thickoutline) >= 1; const isAdditive = Math.abs(additive) >= 1; this.positions[0] = x; this.positions[1] = y; this.positions[2] = 0; this.colors[0] = r; this.colors[1] = g; this.colors[2] = b; this.colors[3] = a * blendProgress; if (isTextured) { this.uvs[0] = 0.5; this.uvs[1] = 0.5; } const quarterPi = Math.PI * 0.25; for (let k = 1; k <= sides + 1; k++) { const p = (k - 1) / sides; const pTwoPi = p * 2 * Math.PI; const angSum = pTwoPi + ang + quarterPi; this.positions[k * 3 + 0] = x + rad * Math.cos(angSum) * this.aspecty; this.positions[k * 3 + 1] = y + rad * Math.sin(angSum); this.positions[k * 3 + 2] = 0; this.colors[k * 4 + 0] = r2; this.colors[k * 4 + 1] = g2; this.colors[k * 4 + 2] = b2; this.colors[k * 4 + 3] = a2 * blendProgress; if (isTextured) { const texAngSum = pTwoPi + texAng + quarterPi; this.uvs[k * 2 + 0] = 0.5 + 0.5 * Math.cos(texAngSum) / texZoom * this.aspecty; this.uvs[k * 2 + 1] = 0.5 + 0.5 * Math.sin(texAngSum) / texZoom; } if (hasBorder) { this.borderPositions[(k - 1) * 3 + 0] = this.positions[k * 3 + 0]; this.borderPositions[(k - 1) * 3 + 1] = this.positions[k * 3 + 1]; this.borderPositions[(k - 1) * 3 + 2] = this.positions[k * 3 + 2]; } } this.mdVSShapeFrame = mdVSShapeFrame; this.drawCustomShapeInstance(prevTexture, sides, isTextured, hasBorder, isBorderThick, isAdditive); } const mdVSUserKeysShape = presetEquationRunner.mdVSUserKeysShapes[this.index]; const mdVSNewFrameMapShape = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(this.mdVSShapeFrame, mdVSUserKeysShape); // eslint-disable-next-line no-param-reassign presetEquationRunner.mdVSFrameMapShapes[this.index] = mdVSNewFrameMapShape; } else { // eslint-disable-next-line max-len this.setupShapeBuffers(presetEquationRunner.preset.globalPools.perFrame.wrap.value); const baseVals = presetEquationRunner.preset.shapes[this.index].baseVals; const varPool = presetEquationRunner.preset.globalPools[`shapePerFrame${this.index}`]; _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(varPool, globalVars, presetEquationRunner.globalKeys); // If we aren't setting these every instance, set them initially if (!presetEquationRunner.preset.shapes[this.index].frame_eqs) { presetEquationRunner.preset.restore_qs(); } _utils__WEBPACK_IMPORTED_MODULE_0__["default"].setWasm(varPool, presetEquationRunner.mdVSTShapeInits[this.index], presetEquationRunner.ts); presetEquationRunner.preset.save_ts(); varPool.x.value = baseVals.x; varPool.y.value = baseVals.y; varPool.rad.value = baseVals.rad; varPool.ang.value = baseVals.ang; varPool.r.value = baseVals.r; varPool.g.value = baseVals.g; varPool.b.value = baseVals.b; varPool.a.value = baseVals.a; varPool.r2.value = baseVals.r2; varPool.g2.value = baseVals.g2; varPool.b2.value = baseVals.b2; varPool.a2.value = baseVals.a2; varPool.border_r.value = baseVals.border_r; varPool.border_g.value = baseVals.border_g; varPool.border_b.value = baseVals.border_b; varPool.border_a.value = baseVals.border_a; varPool.thickoutline.value = baseVals.thickoutline; varPool.textured.value = baseVals.textured; varPool.tex_zoom.value = baseVals.tex_zoom; varPool.tex_ang.value = baseVals.tex_ang; varPool.additive.value = baseVals.additive; presetEquationRunner.preset.shapes[this.index].frame_eqs_save(); const numInst = Math.clamp(baseVals.num_inst, 1, 1024); for (let j = 0; j < numInst; j++) { varPool.instance.value = j; // this condition should check the JS equations because of comments if (presetEquationRunner.preset.shapes[this.index].frame_eqs) { presetEquationRunner.preset.shapes[this.index].frame_eqs_restore(); presetEquationRunner.preset.restore_qs(); presetEquationRunner.preset.restore_ts(); presetEquationRunner.preset.shapes[this.index].frame_eqs(); } let sides = varPool.sides.value; sides = Math.clamp(sides, 3, 100); sides = Math.floor(sides); const rad = varPool.rad.value; const ang = varPool.ang.value; const x = varPool.x.value * 2 - 1; const y = varPool.y.value * -2 + 1; const r = varPool.r.value; const g = varPool.g.value; const b = varPool.b.value; const a = varPool.a.value; const r2 = varPool.r2.value; const g2 = varPool.g2.value; const b2 = varPool.b2.value; const a2 = varPool.a2.value; const borderR = varPool.border_r.value; const borderG = varPool.border_g.value; const borderB = varPool.border_b.value; const borderA = varPool.border_a.value; this.borderColor = [borderR, borderG, borderB, borderA * blendProgress]; const thickoutline = varPool.thickoutline.value; const textured = varPool.textured.value; const texZoom = varPool.tex_zoom.value; const texAng = varPool.tex_ang.value; const additive = varPool.additive.value; const hasBorder = this.borderColor[3] > 0; const isTextured = Math.abs(textured) >= 1; const isBorderThick = Math.abs(thickoutline) >= 1; const isAdditive = Math.abs(additive) >= 1; this.positions[0] = x; this.positions[1] = y; this.positions[2] = 0; this.colors[0] = r; this.colors[1] = g; this.colors[2] = b; this.colors[3] = a * blendProgress; if (isTextured) { this.uvs[0] = 0.5; this.uvs[1] = 0.5; } const quarterPi = Math.PI * 0.25; for (let k = 1; k <= sides + 1; k++) { const p = (k - 1) / sides; const pTwoPi = p * 2 * Math.PI; const angSum = pTwoPi + ang + quarterPi; this.positions[k * 3 + 0] = x + rad * Math.cos(angSum) * this.aspecty; this.positions[k * 3 + 1] = y + rad * Math.sin(angSum); this.positions[k * 3 + 2] = 0; this.colors[k * 4 + 0] = r2; this.colors[k * 4 + 1] = g2; this.colors[k * 4 + 2] = b2; this.colors[k * 4 + 3] = a2 * blendProgress; if (isTextured) { const texAngSum = pTwoPi + texAng + quarterPi; this.uvs[k * 2 + 0] = 0.5 + 0.5 * Math.cos(texAngSum) / texZoom * this.aspecty; this.uvs[k * 2 + 1] = 0.5 + 0.5 * Math.sin(texAngSum) / texZoom; } if (hasBorder) { this.borderPositions[(k - 1) * 3 + 0] = this.positions[k * 3 + 0]; this.borderPositions[(k - 1) * 3 + 1] = this.positions[k * 3 + 1]; this.borderPositions[(k - 1) * 3 + 2] = this.positions[k * 3 + 2]; } } this.drawCustomShapeInstance(prevTexture, sides, isTextured, hasBorder, isBorderThick, isAdditive); } } } } setupShapeBuffers(wrap) { this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.DYNAMIC_DRAW); this.gl.vertexAttribPointer(this.aPosLocation, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.colorVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.colors, this.gl.DYNAMIC_DRAW); this.gl.vertexAttribPointer(this.aColorLocation, 4, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aColorLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.uvVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.uvs, this.gl.DYNAMIC_DRAW); this.gl.vertexAttribPointer(this.aUvLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aUvLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.borderPositionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.borderPositions, this.gl.DYNAMIC_DRAW); this.gl.vertexAttribPointer(this.aBorderPosLoc, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aBorderPosLoc); const wrapping = wrap !== 0 ? this.gl.REPEAT : this.gl.CLAMP_TO_EDGE; this.gl.samplerParameteri(this.mainSampler, this.gl.TEXTURE_WRAP_S, wrapping); this.gl.samplerParameteri(this.mainSampler, this.gl.TEXTURE_WRAP_T, wrapping); } drawCustomShapeInstance(prevTexture, sides, isTextured, hasBorder, isBorderThick, isAdditive) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferSubData(this.gl.ARRAY_BUFFER, 0, this.positions, 0, (sides + 2) * 3); this.gl.vertexAttribPointer(this.aPosLocation, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.colorVertexBuf); this.gl.bufferSubData(this.gl.ARRAY_BUFFER, 0, this.colors, 0, (sides + 2) * 4); this.gl.vertexAttribPointer(this.aColorLocation, 4, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aColorLocation); if (isTextured) { this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.uvVertexBuf); this.gl.bufferSubData(this.gl.ARRAY_BUFFER, 0, this.uvs, 0, (sides + 2) * 2); this.gl.vertexAttribPointer(this.aUvLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aUvLocation); } this.gl.uniform1f(this.texturedLoc, isTextured ? 1 : 0); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, prevTexture); this.gl.bindSampler(0, this.mainSampler); this.gl.uniform1i(this.textureLoc, 0); if (isAdditive) { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); } else { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); } this.gl.drawArrays(this.gl.TRIANGLE_FAN, 0, sides + 2); if (hasBorder) { this.gl.useProgram(this.borderShaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.borderPositionVertexBuf); this.gl.bufferSubData(this.gl.ARRAY_BUFFER, 0, this.borderPositions, 0, (sides + 1) * 3); this.gl.vertexAttribPointer(this.aBorderPosLoc, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aBorderPosLoc); this.gl.uniform4fv(this.uBorderColorLoc, this.borderColor); // TODO: use drawArraysInstanced const instances = isBorderThick ? 4 : 1; for (let i = 0; i < instances; i++) { const offset = 2; if (i === 0) { this.gl.uniform2fv(this.thickOffsetLoc, [0, 0]); } else if (i === 1) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, 0]); } else if (i === 2) { this.gl.uniform2fv(this.thickOffsetLoc, [0, offset / this.texsizeY]); } else if (i === 3) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, offset / this.texsizeY]); } this.gl.drawArrays(this.gl.LINE_STRIP, 0, sides + 1); } } } } /***/ }), /***/ "./src/rendering/sprites/border.js": /*!*****************************************!*\ !*** ./src/rendering/sprites/border.js ***! \*****************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Border; }); /* harmony import */ var _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shaders/shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class Border { constructor(gl, opts = {}) { this.gl = gl; this.positions = new Float32Array(72); this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.floatPrecision = _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); this.vertexBuf = this.gl.createBuffer(); } updateGlobals(opts) { this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es in vec3 aPos; void main(void) { gl_Position = vec4(aPos, 1.0); } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; out vec4 fragColor; uniform vec4 u_color; void main(void) { fragColor = u_color; } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.aPosLoc = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.colorLoc = this.gl.getUniformLocation(this.shaderProgram, "u_color"); } addTriangle(offset, point1, point2, point3) { this.positions[offset + 0] = point1[0]; this.positions[offset + 1] = point1[1]; this.positions[offset + 2] = point1[2]; this.positions[offset + 3] = point2[0]; this.positions[offset + 4] = point2[1]; this.positions[offset + 5] = point2[2]; this.positions[offset + 6] = point3[0]; this.positions[offset + 7] = point3[1]; this.positions[offset + 8] = point3[2]; } // based on https://github.com/mrdoob/three.js/blob/master/src/geometries/PlaneGeometry.js generateBorder(borderColor, borderSize, prevBorderSize) { if (borderSize > 0 && borderColor[3] > 0) { const width = 2; const height = 2; const widthHalf = width / 2; const heightHalf = height / 2; const prevBorderWidth = prevBorderSize / 2; const borderWidth = borderSize / 2 + prevBorderWidth; const prevBorderWidthWidth = prevBorderWidth * width; const prevBorderWidthHeight = prevBorderWidth * height; const borderWidthWidth = borderWidth * width; const borderWidthHeight = borderWidth * height; // 1st side let point1 = [-widthHalf + prevBorderWidthWidth, -heightHalf + borderWidthHeight, 0]; let point2 = [-widthHalf + prevBorderWidthWidth, heightHalf - borderWidthHeight, 0]; let point3 = [-widthHalf + borderWidthWidth, heightHalf - borderWidthHeight, 0]; let point4 = [-widthHalf + borderWidthWidth, -heightHalf + borderWidthHeight, 0]; this.addTriangle(0, point4, point2, point1); this.addTriangle(9, point4, point3, point2); // 2nd side point1 = [widthHalf - prevBorderWidthWidth, -heightHalf + borderWidthHeight, 0]; point2 = [widthHalf - prevBorderWidthWidth, heightHalf - borderWidthHeight, 0]; point3 = [widthHalf - borderWidthWidth, heightHalf - borderWidthHeight, 0]; point4 = [widthHalf - borderWidthWidth, -heightHalf + borderWidthHeight, 0]; this.addTriangle(18, point1, point2, point4); this.addTriangle(27, point2, point3, point4); // Top point1 = [-widthHalf + prevBorderWidthWidth, -heightHalf + prevBorderWidthHeight, 0]; point2 = [-widthHalf + prevBorderWidthWidth, borderWidthHeight - heightHalf, 0]; point3 = [widthHalf - prevBorderWidthWidth, borderWidthHeight - heightHalf, 0]; point4 = [widthHalf - prevBorderWidthWidth, -heightHalf + prevBorderWidthHeight, 0]; this.addTriangle(36, point4, point2, point1); this.addTriangle(45, point4, point3, point2); // Bottom point1 = [-widthHalf + prevBorderWidthWidth, heightHalf - prevBorderWidthHeight, 0]; point2 = [-widthHalf + prevBorderWidthWidth, heightHalf - borderWidthHeight, 0]; point3 = [widthHalf - prevBorderWidthWidth, heightHalf - borderWidthHeight, 0]; point4 = [widthHalf - prevBorderWidthWidth, heightHalf - prevBorderWidthHeight, 0]; this.addTriangle(54, point1, point2, point4); this.addTriangle(63, point2, point3, point4); return true; } return false; } drawBorder(borderColor, borderSize, prevBorderSize) { if (this.generateBorder(borderColor, borderSize, prevBorderSize)) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aPosLoc, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLoc); this.gl.uniform4fv(this.colorLoc, borderColor); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawArrays(this.gl.TRIANGLES, 0, this.positions.length / 3); } } } /***/ }), /***/ "./src/rendering/sprites/darkenCenter.js": /*!***********************************************!*\ !*** ./src/rendering/sprites/darkenCenter.js ***! \***********************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return CustomShape; }); /* harmony import */ var _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shaders/shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class CustomShape { constructor(gl, opts) { this.gl = gl; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.generatePositions(); this.colors = new Float32Array([0, 0, 0, 3 / 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); this.positionVertexBuf = this.gl.createBuffer(); this.colorVertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); } updateGlobals(opts) { this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.generatePositions(); } generatePositions() { const halfSize = 0.05; this.positions = new Float32Array([0, 0, 0, -halfSize * this.aspecty, 0, 0, 0, -halfSize, 0, halfSize * this.aspecty, 0, 0, 0, halfSize, 0, -halfSize * this.aspecty, 0, 0]); } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es in vec3 aPos; in vec4 aColor; out vec4 vColor; void main(void) { vColor = aColor; gl_Position = vec4(aPos, 1.0); } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec4 vColor; out vec4 fragColor; void main(void) { fragColor = vColor; } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.aPosLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.aColorLocation = this.gl.getAttribLocation(this.shaderProgram, "aColor"); } drawDarkenCenter(mdVSFrame) { if (mdVSFrame.darken_center !== 0) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aPosLocation, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.colorVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.colors, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aColorLocation, 4, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aColorLocation); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawArrays(this.gl.TRIANGLE_FAN, 0, this.positions.length / 3); } } } /***/ }), /***/ "./src/rendering/text/titleText.js": /*!*****************************************!*\ !*** ./src/rendering/text/titleText.js ***! \*****************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return TitleText; }); /* harmony import */ var _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shaders/shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); class TitleText { constructor(gl, opts = {}) { this.gl = gl; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.buildPositions(); this.textTexture = this.gl.createTexture(); this.indexBuf = gl.createBuffer(); this.positionVertexBuf = this.gl.createBuffer(); this.vertexBuf = this.gl.createBuffer(); this.canvas = document.createElement("canvas"); this.canvas.width = this.texsizeX; this.canvas.height = this.texsizeY; this.context2D = this.canvas.getContext("2d"); this.floatPrecision = _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); } generateTitleTexture(text) { this.context2D.clearRect(0, 0, this.texsizeX, this.texsizeY); this.fontSize = Math.floor(16 * (this.texsizeX / 256)); this.fontSize = Math.max(this.fontSize, 6); this.context2D.font = `italic ${this.fontSize}px Times New Roman`; let titleText = text; let textLength = this.context2D.measureText(titleText).width; if (textLength > this.texsizeX) { const percentToKeep = 0.91 * (this.texsizeX / textLength); titleText = `${titleText.substring(0, Math.floor(titleText.length * percentToKeep))}...`; textLength = this.context2D.measureText(titleText).width; } this.context2D.fillStyle = "#FFFFFF"; this.context2D.fillText(titleText, (this.texsizeX - textLength) / 2, this.texsizeY / 2); const imageData = new Uint8Array(this.context2D.getImageData(0, 0, this.texsizeX, this.texsizeY).data.buffer); this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textTexture); this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.texsizeX, this.texsizeY, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, imageData); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); this.gl.generateMipmap(this.gl.TEXTURE_2D); this.gl.bindTexture(this.gl.TEXTURE_2D, null); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.canvas.width = this.texsizeX; this.canvas.height = this.texsizeY; } // based on https://github.com/mrdoob/three.js/blob/master/src/geometries/PlaneGeometry.js buildPositions() { const width = 2; const height = 2; const widthHalf = width / 2; const heightHalf = height / 2; const gridX = 15; const gridY = 7; const gridX1 = gridX + 1; const gridY1 = gridY + 1; const segmentWidth = width / gridX; const segmentHeight = height / gridY; const vertices = []; for (let iy = 0; iy < gridY1; iy++) { const y = iy * segmentHeight - heightHalf; for (let ix = 0; ix < gridX1; ix++) { const x = ix * segmentWidth - widthHalf; vertices.push(x, -y, 0); } } const indices = []; for (let iy = 0; iy < gridY; iy++) { for (let ix = 0; ix < gridX; ix++) { const a = ix + gridX1 * iy; const b = ix + gridX1 * (iy + 1); const c = ix + 1 + gridX1 * (iy + 1); const d = ix + 1 + gridX1 * iy; indices.push(a, b, d); indices.push(b, c, d); } } this.vertices = new Float32Array(vertices); this.indices = new Uint16Array(indices); } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, `#version 300 es const vec2 halfmad = vec2(0.5); in vec2 aPos; in vec2 aUv; out vec2 uv_orig; out vec2 uv; void main(void) { gl_Position = vec4(aPos, 0.0, 1.0); uv_orig = aPos * halfmad + halfmad; uv = aUv; }`); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, `#version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec2 uv_orig; in vec2 uv; out vec4 fragColor; uniform sampler2D uTexture; uniform float textColor; void main(void) { fragColor = texture(uTexture, uv) * vec4(textColor); }`); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.positionLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.uvLocation = this.gl.getAttribLocation(this.shaderProgram, "aUv"); this.textureLoc = this.gl.getUniformLocation(this.shaderProgram, "uTexture"); this.textColorLoc = this.gl.getUniformLocation(this.shaderProgram, "textColor"); } generateUvs(progress, flip, globalVars) { const gridX = 15; const gridY = 7; const gridX1 = gridX + 1; const gridY1 = gridY + 1; const uvs = []; const vertClip = 0.75; for (let j = 0; j < gridY1; j++) { for (let i = 0; i < gridX1; i++) { const u = i / gridX; const v = (j / gridY - 0.5) * vertClip + 0.5; const x = u * 2.0 - 1.0; let y = v * 2.0 - 1.0; if (progress >= 1) { y += 1.0 / this.texsizeY; } uvs.push(x, flip ? y : -y); } } const rampedProgress = Math.max(0, 1 - progress * 1.5); const t2 = rampedProgress ** 1.8 * 1.3; for (let j = 0; j < gridY1; j++) { for (let i = 0; i < gridX1; i++) { const idx = j * gridX1 + i; uvs[idx] += t2 * 0.07 * Math.sin(globalVars.time * 0.31 + uvs[idx] * 0.39 - uvs[idx + 1] * 1.94); uvs[idx] += t2 * 0.044 * Math.sin(globalVars.time * 0.81 - uvs[idx] * 1.91 + uvs[idx + 1] * 0.27); uvs[idx] += t2 * 0.061 * Math.sin(globalVars.time * 1.31 + uvs[idx] * 0.61 + uvs[idx + 1] * 0.74); uvs[idx + 1] += t2 * 0.061 * Math.sin(globalVars.time * 0.37 + uvs[idx] * 1.83 + uvs[idx + 1] * 0.69); uvs[idx + 1] += t2 * 0.07 * Math.sin(globalVars.time * 0.67 + uvs[idx] * 0.42 - uvs[idx + 1] * 1.39); uvs[idx + 1] += t2 * 0.087 * Math.sin(globalVars.time * 1.07 + uvs[idx] * 3.55 + uvs[idx + 1] * 0.89); } } const scale = 1.01 / (progress ** 0.21 + 0.01); for (let i = 0; i < uvs.length / 2; i++) { uvs[i * 2] *= scale; uvs[i * 2 + 1] *= scale * this.invAspecty; // get back UVs uvs[i * 2] = (uvs[i * 2] + 1) / 2.0; uvs[i * 2 + 1] = (uvs[i * 2 + 1] + 1) / 2.0; } return new Float32Array(uvs); } renderTitle(progress, flip, globalVars) { this.gl.useProgram(this.shaderProgram); const progressUvs = this.generateUvs(progress, flip, globalVars); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.indexBuf); this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this.indices, this.gl.STATIC_DRAW); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertices, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.positionLocation, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.positionLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, progressUvs, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.uvLocation, 2, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.uvLocation); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textTexture); this.gl.uniform1i(this.textureLoc, 0); this.gl.uniform1f(this.textColorLoc, progress ** 0.3); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.drawElements(this.gl.TRIANGLES, this.indices.length, this.gl.UNSIGNED_SHORT, 0); } } /***/ }), /***/ "./src/rendering/waves/basicWaveform.js": /*!**********************************************!*\ !*** ./src/rendering/waves/basicWaveform.js ***! \**********************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return BasicWaveform; }); /* harmony import */ var _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shaders/shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); /* harmony import */ var _waveUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./waveUtils */ "./src/rendering/waves/waveUtils.js"); class BasicWaveform { constructor(gl, opts = {}) { this.gl = gl; const numAudioSamples = 512; this.positions = new Float32Array(numAudioSamples * 3); this.positions2 = new Float32Array(numAudioSamples * 3); this.oldPositions = new Float32Array(numAudioSamples * 3); this.oldPositions2 = new Float32Array(numAudioSamples * 3); this.smoothedPositions = new Float32Array((numAudioSamples * 2 - 1) * 3); this.smoothedPositions2 = new Float32Array((numAudioSamples * 2 - 1) * 3); this.color = [0, 0, 0, 1]; this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.floatPrecision = _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_0__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); this.vertexBuf = this.gl.createBuffer(); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es in vec3 aPos; uniform vec2 thickOffset; void main(void) { gl_Position = vec4(aPos + vec3(thickOffset, 0.0), 1.0); } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; out vec4 fragColor; uniform vec4 u_color; void main(void) { fragColor = u_color; } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.aPosLoc = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.colorLoc = this.gl.getUniformLocation(this.shaderProgram, "u_color"); this.thickOffsetLoc = this.gl.getUniformLocation(this.shaderProgram, "thickOffset"); } static processWaveform(timeArray, mdVSFrame) { const waveform = []; const scale = mdVSFrame.wave_scale / 128.0; const smooth = mdVSFrame.wave_smoothing; const smooth2 = scale * (1.0 - smooth); waveform.push(timeArray[0] * scale); for (let i = 1; i < timeArray.length; i++) { waveform.push(timeArray[i] * smooth2 + waveform[i - 1] * smooth); } return waveform; } generateWaveform(blending, blendProgress, timeArrayL, timeArrayR, mdVSFrame) { let alpha = mdVSFrame.wave_a; const vol = (mdVSFrame.bass + mdVSFrame.mid + mdVSFrame.treb) / 3.0; if (vol > -0.01 && alpha > 0.001 && timeArrayL.length > 0) { const waveL = BasicWaveform.processWaveform(timeArrayL, mdVSFrame); const waveR = BasicWaveform.processWaveform(timeArrayR, mdVSFrame); const newWaveMode = Math.floor(mdVSFrame.wave_mode) % 8; const oldWaveMode = Math.floor(mdVSFrame.old_wave_mode) % 8; const wavePosX = mdVSFrame.wave_x * 2.0 - 1.0; const wavePosY = mdVSFrame.wave_y * 2.0 - 1.0; this.numVert = 0; this.oldNumVert = 0; const its = blending && newWaveMode !== oldWaveMode ? 2 : 1; for (let it = 0; it < its; it++) { const waveMode = it === 0 ? newWaveMode : oldWaveMode; let fWaveParam2 = mdVSFrame.wave_mystery; if ((waveMode === 0 || waveMode === 1 || waveMode === 4) && (fWaveParam2 < -1 || fWaveParam2 > 1)) { fWaveParam2 = fWaveParam2 * 0.5 + 0.5; fWaveParam2 -= Math.floor(fWaveParam2); fWaveParam2 = Math.abs(fWaveParam2); fWaveParam2 = fWaveParam2 * 2 - 1; } let numVert; let positions; let positions2; if (it === 0) { positions = this.positions; positions2 = this.positions2; } else { positions = this.oldPositions; positions2 = this.oldPositions2; } alpha = mdVSFrame.wave_a; if (waveMode === 0) { if (mdVSFrame.modwavealphabyvolume > 0) { const alphaDiff = mdVSFrame.modwavealphaend - mdVSFrame.modwavealphastart; alpha *= (vol - mdVSFrame.modwavealphastart) / alphaDiff; } alpha = Math.clamp(alpha, 0, 1); numVert = Math.floor(waveL.length / 2) + 1; const numVertInv = 1.0 / (numVert - 1); const sampleOffset = Math.floor((waveL.length - numVert) / 2); for (let i = 0; i < numVert - 1; i++) { let rad = 0.5 + 0.4 * waveR[i + sampleOffset] + fWaveParam2; const ang = i * numVertInv * 2 * Math.PI + mdVSFrame.time * 0.2; if (i < numVert / 10) { let mix = i / (numVert * 0.1); mix = 0.5 - 0.5 * Math.cos(mix * Math.PI); const rad2 = 0.5 + 0.4 * waveR[i + numVert + sampleOffset] + fWaveParam2; rad = (1.0 - mix) * rad2 + rad * mix; } positions[i * 3 + 0] = rad * Math.cos(ang) * this.aspecty + wavePosX; positions[i * 3 + 1] = rad * Math.sin(ang) * this.aspectx + wavePosY; positions[i * 3 + 2] = 0; } // connect the loop positions[(numVert - 1) * 3 + 0] = positions[0]; positions[(numVert - 1) * 3 + 1] = positions[1]; positions[(numVert - 1) * 3 + 2] = 0; } else if (waveMode === 1) { alpha *= 1.25; if (mdVSFrame.modwavealphabyvolume > 0) { const alphaDiff = mdVSFrame.modwavealphaend - mdVSFrame.modwavealphastart; alpha *= (vol - mdVSFrame.modwavealphastart) / alphaDiff; } alpha = Math.clamp(alpha, 0, 1); numVert = Math.floor(waveL.length / 2); for (let i = 0; i < numVert; i++) { const rad = 0.53 + 0.43 * waveR[i] + fWaveParam2; const ang = waveL[i + 32] * 0.5 * Math.PI + mdVSFrame.time * 2.3; positions[i * 3 + 0] = rad * Math.cos(ang) * this.aspecty + wavePosX; positions[i * 3 + 1] = rad * Math.sin(ang) * this.aspectx + wavePosY; positions[i * 3 + 2] = 0; } } else if (waveMode === 2) { if (this.texsizeX < 1024) { alpha *= 0.09; } else if (this.texsizeX >= 1024 && this.texsizeX < 2048) { alpha *= 0.11; } else { alpha *= 0.13; } if (mdVSFrame.modwavealphabyvolume > 0) { const alphaDiff = mdVSFrame.modwavealphaend - mdVSFrame.modwavealphastart; alpha *= (vol - mdVSFrame.modwavealphastart) / alphaDiff; } alpha = Math.clamp(alpha, 0, 1); numVert = waveL.length; for (let i = 0; i < waveL.length; i++) { positions[i * 3 + 0] = waveR[i] * this.aspecty + wavePosX; positions[i * 3 + 1] = waveL[(i + 32) % waveL.length] * this.aspectx + wavePosY; positions[i * 3 + 2] = 0; } } else if (waveMode === 3) { if (this.texsizeX < 1024) { alpha *= 0.15; } else if (this.texsizeX >= 1024 && this.texsizeX < 2048) { alpha *= 0.22; } else { alpha *= 0.33; } alpha *= 1.3; alpha *= mdVSFrame.treb * mdVSFrame.treb; // should be treb_imm if (mdVSFrame.modwavealphabyvolume > 0) { const alphaDiff = mdVSFrame.modwavealphaend - mdVSFrame.modwavealphastart; alpha *= (vol - mdVSFrame.modwavealphastart) / alphaDiff; } alpha = Math.clamp(alpha, 0, 1); numVert = waveL.length; for (let i = 0; i < waveL.length; i++) { positions[i * 3 + 0] = waveR[i] * this.aspecty + wavePosX; positions[i * 3 + 1] = waveL[(i + 32) % waveL.length] * this.aspectx + wavePosY; positions[i * 3 + 2] = 0; } } else if (waveMode === 4) { if (mdVSFrame.modwavealphabyvolume > 0) { const alphaDiff = mdVSFrame.modwavealphaend - mdVSFrame.modwavealphastart; alpha *= (vol - mdVSFrame.modwavealphastart) / alphaDiff; } alpha = Math.clamp(alpha, 0, 1); numVert = waveL.length; if (numVert > this.texsizeX / 3) { numVert = Math.floor(this.texsizeX / 3); } const numVertInv = 1.0 / numVert; const sampleOffset = Math.floor((waveL.length - numVert) / 2); const w1 = 0.45 + 0.5 * (fWaveParam2 * 0.5 + 0.5); const w2 = 1.0 - w1; for (let i = 0; i < numVert; i++) { let x = 2.0 * i * numVertInv + (wavePosX - 1) + waveR[(i + 25 + sampleOffset) % waveL.length] * 0.44; let y = waveL[i + sampleOffset] * 0.47 + wavePosY; // momentum if (i > 1) { x = x * w2 + w1 * (positions[(i - 1) * 3 + 0] * 2.0 - positions[(i - 2) * 3 + 0]); y = y * w2 + w1 * (positions[(i - 1) * 3 + 1] * 2.0 - positions[(i - 2) * 3 + 1]); } positions[i * 3 + 0] = x; positions[i * 3 + 1] = y; positions[i * 3 + 2] = 0; } } else if (waveMode === 5) { if (this.texsizeX < 1024) { alpha *= 0.09; } else if (this.texsizeX >= 1024 && this.texsizeX < 2048) { alpha *= 0.11; } else { alpha *= 0.13; } if (mdVSFrame.modwavealphabyvolume > 0) { const alphaDiff = mdVSFrame.modwavealphaend - mdVSFrame.modwavealphastart; alpha *= (vol - mdVSFrame.modwavealphastart) / alphaDiff; } alpha = Math.clamp(alpha, 0, 1); const cosRot = Math.cos(mdVSFrame.time * 0.3); const sinRot = Math.sin(mdVSFrame.time * 0.3); numVert = waveL.length; for (let i = 0; i < waveL.length; i++) { const ioff = (i + 32) % waveL.length; const x0 = waveR[i] * waveL[ioff] + waveL[i] * waveR[ioff]; const y0 = waveR[i] * waveR[i] - waveL[ioff] * waveL[ioff]; positions[i * 3 + 0] = (x0 * cosRot - y0 * sinRot) * (this.aspecty + wavePosX); positions[i * 3 + 1] = (x0 * sinRot + y0 * cosRot) * (this.aspectx + wavePosY); positions[i * 3 + 2] = 0; } } else if (waveMode === 6 || waveMode === 7) { if (mdVSFrame.modwavealphabyvolume > 0) { const alphaDiff = mdVSFrame.modwavealphaend - mdVSFrame.modwavealphastart; alpha *= (vol - mdVSFrame.modwavealphastart) / alphaDiff; } alpha = Math.clamp(alpha, 0, 1); numVert = Math.floor(waveL.length / 2); if (numVert > this.texsizeX / 3) { numVert = Math.floor(this.texsizeX / 3); } const sampleOffset = Math.floor((waveL.length - numVert) / 2); const ang = Math.PI * 0.5 * fWaveParam2; let dx = Math.cos(ang); let dy = Math.sin(ang); const edgex = [wavePosX * Math.cos(ang + Math.PI * 0.5) - dx * 3.0, wavePosX * Math.cos(ang + Math.PI * 0.5) + dx * 3.0]; const edgey = [wavePosX * Math.sin(ang + Math.PI * 0.5) - dy * 3.0, wavePosX * Math.sin(ang + Math.PI * 0.5) + dy * 3.0]; for (let i = 0; i < 2; i++) { for (let j = 0; j < 4; j++) { let t; let bClip = false; switch (j) { case 0: if (edgex[i] > 1.1) { t = (1.1 - edgex[1 - i]) / (edgex[i] - edgex[1 - i]); bClip = true; } break; case 1: if (edgex[i] < -1.1) { t = (-1.1 - edgex[1 - i]) / (edgex[i] - edgex[1 - i]); bClip = true; } break; case 2: if (edgey[i] > 1.1) { t = (1.1 - edgey[1 - i]) / (edgey[i] - edgey[1 - i]); bClip = true; } break; case 3: if (edgey[i] < -1.1) { t = (-1.1 - edgey[1 - i]) / (edgey[i] - edgey[1 - i]); bClip = true; } break; default: } if (bClip) { const dxi = edgex[i] - edgex[1 - i]; const dyi = edgey[i] - edgey[1 - i]; edgex[i] = edgex[1 - i] + dxi * t; edgey[i] = edgey[1 - i] + dyi * t; } } } dx = (edgex[1] - edgex[0]) / numVert; dy = (edgey[1] - edgey[0]) / numVert; const ang2 = Math.atan2(dy, dx); const perpDx = Math.cos(ang2 + Math.PI * 0.5); const perpDy = Math.sin(ang2 + Math.PI * 0.5); if (waveMode === 6) { for (let i = 0; i < numVert; i++) { const sample = waveL[i + sampleOffset]; positions[i * 3 + 0] = edgex[0] + dx * i + perpDx * 0.25 * sample; positions[i * 3 + 1] = edgey[0] + dy * i + perpDy * 0.25 * sample; positions[i * 3 + 2] = 0; } } else if (waveMode === 7) { const sep = (wavePosY * 0.5 + 0.5) ** 2; for (let i = 0; i < numVert; i++) { const sample = waveL[i + sampleOffset]; positions[i * 3 + 0] = edgex[0] + dx * i + perpDx * (0.25 * sample + sep); positions[i * 3 + 1] = edgey[0] + dy * i + perpDy * (0.25 * sample + sep); positions[i * 3 + 2] = 0; } for (let i = 0; i < numVert; i++) { const sample = waveR[i + sampleOffset]; positions2[i * 3 + 0] = edgex[0] + dx * i + perpDx * (0.25 * sample - sep); positions2[i * 3 + 1] = edgey[0] + dy * i + perpDy * (0.25 * sample - sep); positions2[i * 3 + 2] = 0; } } } if (it === 0) { this.positions = positions; this.positions2 = positions2; this.numVert = numVert; this.alpha = alpha; } else { this.oldPositions = positions; this.oldPositions2 = positions2; this.oldNumVert = numVert; this.oldAlpha = alpha; } } const mix = 0.5 - 0.5 * Math.cos(blendProgress * Math.PI); const mix2 = 1 - mix; if (this.oldNumVert > 0) { alpha = mix * this.alpha + mix2 * this.oldAlpha; } let r = Math.clamp(mdVSFrame.wave_r, 0, 1); let g = Math.clamp(mdVSFrame.wave_g, 0, 1); let b = Math.clamp(mdVSFrame.wave_b, 0, 1); if (mdVSFrame.wave_brighten !== 0) { const maxc = Math.max(r, g, b); if (maxc > 0.01) { r /= maxc; g /= maxc; b /= maxc; } } this.color = [r, g, b, alpha]; if (this.oldNumVert > 0) { if (newWaveMode === 7) { const m = (this.oldNumVert - 1) / (this.numVert * 2); for (let i = 0; i < this.numVert; i++) { const fIdx = i * m; const nIdx = Math.floor(fIdx); const t = fIdx - nIdx; const x = this.oldPositions[nIdx * 3 + 0] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 0] * t; const y = this.oldPositions[nIdx * 3 + 1] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 1] * t; this.positions[i * 3 + 0] = this.positions[i * 3 + 0] * mix + x * mix2; this.positions[i * 3 + 1] = this.positions[i * 3 + 1] * mix + y * mix2; this.positions[i * 3 + 2] = 0; } for (let i = 0; i < this.numVert; i++) { const fIdx = (i + this.numVert) * m; const nIdx = Math.floor(fIdx); const t = fIdx - nIdx; const x = this.oldPositions[nIdx * 3 + 0] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 0] * t; const y = this.oldPositions[nIdx * 3 + 1] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 1] * t; this.positions2[i * 3 + 0] = this.positions2[i * 3 + 0] * mix + x * mix2; this.positions2[i * 3 + 1] = this.positions2[i * 3 + 1] * mix + y * mix2; this.positions2[i * 3 + 2] = 0; } } else if (oldWaveMode === 7) { const halfNumVert = this.numVert / 2; const m = (this.oldNumVert - 1) / halfNumVert; for (let i = 0; i < halfNumVert; i++) { const fIdx = i * m; const nIdx = Math.floor(fIdx); const t = fIdx - nIdx; const x = this.oldPositions[nIdx * 3 + 0] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 0] * t; const y = this.oldPositions[nIdx * 3 + 1] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 1] * t; this.positions[i * 3 + 0] = this.positions[i * 3 + 0] * mix + x * mix2; this.positions[i * 3 + 1] = this.positions[i * 3 + 1] * mix + y * mix2; this.positions[i * 3 + 2] = 0; } for (let i = 0; i < halfNumVert; i++) { const fIdx = i * m; const nIdx = Math.floor(fIdx); const t = fIdx - nIdx; const x = this.oldPositions2[nIdx * 3 + 0] * (1 - t) + this.oldPositions2[(nIdx + 1) * 3 + 0] * t; const y = this.oldPositions2[nIdx * 3 + 1] * (1 - t) + this.oldPositions2[(nIdx + 1) * 3 + 1] * t; this.positions2[i * 3 + 0] = this.positions[(i + halfNumVert) * 3 + 0] * mix + x * mix2; this.positions2[i * 3 + 1] = this.positions[(i + halfNumVert) * 3 + 1] * mix + y * mix2; this.positions2[i * 3 + 2] = 0; } } else { const m = (this.oldNumVert - 1) / this.numVert; for (let i = 0; i < this.numVert; i++) { const fIdx = i * m; const nIdx = Math.floor(fIdx); const t = fIdx - nIdx; const x = this.oldPositions[nIdx * 3 + 0] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 0] * t; const y = this.oldPositions[nIdx * 3 + 1] * (1 - t) + this.oldPositions[(nIdx + 1) * 3 + 1] * t; this.positions[i * 3 + 0] = this.positions[i * 3 + 0] * mix + x * mix2; this.positions[i * 3 + 1] = this.positions[i * 3 + 1] * mix + y * mix2; this.positions[i * 3 + 2] = 0; } } } for (let i = 0; i < this.numVert; i++) { this.positions[i * 3 + 1] = -this.positions[i * 3 + 1]; } this.smoothedNumVert = this.numVert * 2 - 1; _waveUtils__WEBPACK_IMPORTED_MODULE_1__["default"].smoothWave(this.positions, this.smoothedPositions, this.numVert); if (newWaveMode === 7 || oldWaveMode === 7) { for (let i = 0; i < this.numVert; i++) { this.positions2[i * 3 + 1] = -this.positions2[i * 3 + 1]; } _waveUtils__WEBPACK_IMPORTED_MODULE_1__["default"].smoothWave(this.positions2, this.smoothedPositions2, this.numVert); } return true; } return false; } drawBasicWaveform(blending, blendProgress, timeArrayL, timeArrayR, mdVSFrame) { if (this.generateWaveform(blending, blendProgress, timeArrayL, timeArrayR, mdVSFrame)) { this.gl.useProgram(this.shaderProgram); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.smoothedPositions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aPosLoc, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLoc); this.gl.uniform4fv(this.colorLoc, this.color); let instances = 1; if (mdVSFrame.wave_thick !== 0 || mdVSFrame.wave_dots !== 0) { instances = 4; } if (mdVSFrame.additivewave !== 0) { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); } else { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); } const drawMode = mdVSFrame.wave_dots !== 0 ? this.gl.POINTS : this.gl.LINE_STRIP; // TODO: use drawArraysInstanced for (let i = 0; i < instances; i++) { const offset = 2; if (i === 0) { this.gl.uniform2fv(this.thickOffsetLoc, [0, 0]); } else if (i === 1) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, 0]); } else if (i === 2) { this.gl.uniform2fv(this.thickOffsetLoc, [0, offset / this.texsizeY]); } else if (i === 3) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, offset / this.texsizeY]); } this.gl.drawArrays(drawMode, 0, this.smoothedNumVert); } const waveMode = Math.floor(mdVSFrame.wave_mode) % 8; if (waveMode === 7) { this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.smoothedPositions2, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aPosLoc, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLoc); for (let i = 0; i < instances; i++) { const offset = 2; if (i === 0) { this.gl.uniform2fv(this.thickOffsetLoc, [0, 0]); } else if (i === 1) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, 0]); } else if (i === 2) { this.gl.uniform2fv(this.thickOffsetLoc, [0, offset / this.texsizeY]); } else if (i === 3) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, offset / this.texsizeY]); } this.gl.drawArrays(drawMode, 0, this.smoothedNumVert); } } } } } /***/ }), /***/ "./src/rendering/waves/customWaveform.js": /*!***********************************************!*\ !*** ./src/rendering/waves/customWaveform.js ***! \***********************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return CustomWaveform; }); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils */ "./src/utils.js"); /* harmony import */ var _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../shaders/shaderUtils */ "./src/rendering/shaders/shaderUtils.js"); /* harmony import */ var _waveUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./waveUtils */ "./src/rendering/waves/waveUtils.js"); class CustomWaveform { constructor(index, gl, opts) { this.index = index; this.gl = gl; const maxSamples = 512; this.pointsData = [new Float32Array(maxSamples), new Float32Array(maxSamples)]; this.positions = new Float32Array(maxSamples * 3); this.colors = new Float32Array(maxSamples * 4); this.smoothedPositions = new Float32Array((maxSamples * 2 - 1) * 3); this.smoothedColors = new Float32Array((maxSamples * 2 - 1) * 4); this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; this.positionVertexBuf = this.gl.createBuffer(); this.colorVertexBuf = this.gl.createBuffer(); this.floatPrecision = _shaders_shaderUtils__WEBPACK_IMPORTED_MODULE_1__["default"].getFragmentFloatPrecision(this.gl); this.createShader(); } updateGlobals(opts) { this.texsizeX = opts.texsizeX; this.texsizeY = opts.texsizeY; this.mesh_width = opts.mesh_width; this.mesh_height = opts.mesh_height; this.aspectx = opts.aspectx; this.aspecty = opts.aspecty; this.invAspectx = 1.0 / this.aspectx; this.invAspecty = 1.0 / this.aspecty; } createShader() { this.shaderProgram = this.gl.createProgram(); const vertShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertShader, ` #version 300 es uniform float uSize; uniform vec2 thickOffset; in vec3 aPos; in vec4 aColor; out vec4 vColor; void main(void) { vColor = aColor; gl_PointSize = uSize; gl_Position = vec4(aPos + vec3(thickOffset, 0.0), 1.0); } `.trim()); this.gl.compileShader(vertShader); const fragShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragShader, ` #version 300 es precision ${this.floatPrecision} float; precision highp int; precision mediump sampler2D; in vec4 vColor; out vec4 fragColor; void main(void) { fragColor = vColor; } `.trim()); this.gl.compileShader(fragShader); this.gl.attachShader(this.shaderProgram, vertShader); this.gl.attachShader(this.shaderProgram, fragShader); this.gl.linkProgram(this.shaderProgram); this.aPosLocation = this.gl.getAttribLocation(this.shaderProgram, "aPos"); this.aColorLocation = this.gl.getAttribLocation(this.shaderProgram, "aColor"); this.sizeLoc = this.gl.getUniformLocation(this.shaderProgram, "uSize"); this.thickOffsetLoc = this.gl.getUniformLocation(this.shaderProgram, "thickOffset"); } generateWaveform(timeArrayL, timeArrayR, freqArrayL, freqArrayR, globalVars, presetEquationRunner, waveEqs, alphaMult) { if (waveEqs.baseVals.enabled !== 0 && timeArrayL.length > 0) { let mdVSWaveFrame; if (presetEquationRunner.preset.useWASM) { mdVSWaveFrame = presetEquationRunner.runWaveFrameEquations(this.index, globalVars); } else { const mdVSWave = Object.assign({}, presetEquationRunner.mdVSWaves[this.index], presetEquationRunner.mdVSFrameMapWaves[this.index], presetEquationRunner.mdVSQAfterFrame, presetEquationRunner.mdVSTWaveInits[this.index], globalVars); mdVSWaveFrame = presetEquationRunner.runWaveFrameEquations(this.index, mdVSWave); } const maxSamples = 512; if (Object.prototype.hasOwnProperty.call(mdVSWaveFrame, "samples")) { this.samples = mdVSWaveFrame.samples; } else { this.samples = maxSamples; } if (this.samples > maxSamples) { this.samples = maxSamples; } this.samples = Math.floor(this.samples); const baseVals = presetEquationRunner.preset.waves[this.index].baseVals; const sep = Math.floor(mdVSWaveFrame.sep); const scaling = mdVSWaveFrame.scaling; const spectrum = mdVSWaveFrame.spectrum; const smoothing = mdVSWaveFrame.smoothing; const usedots = baseVals.usedots; const frameR = mdVSWaveFrame.r; const frameG = mdVSWaveFrame.g; const frameB = mdVSWaveFrame.b; const frameA = mdVSWaveFrame.a; const waveScale = presetEquationRunner.preset.baseVals.wave_scale; this.samples -= sep; if (this.samples >= 2 || usedots !== 0 && this.samples >= 1) { const useSpectrum = spectrum !== 0; const scale = (useSpectrum ? 0.15 : 0.004) * scaling * waveScale; const pointsLeft = useSpectrum ? freqArrayL : timeArrayL; const pointsRight = useSpectrum ? freqArrayR : timeArrayR; const j0 = useSpectrum ? 0 : Math.floor((maxSamples - this.samples) / 2 - sep / 2); const j1 = useSpectrum ? 0 : Math.floor((maxSamples - this.samples) / 2 + sep / 2); const t = useSpectrum ? (maxSamples - sep) / this.samples : 1; const mix1 = (smoothing * 0.98) ** 0.5; const mix2 = 1 - mix1; // Milkdrop smooths waveform forward, backward and then scales this.pointsData[0][0] = pointsLeft[j0]; this.pointsData[1][0] = pointsRight[j1]; for (let j = 1; j < this.samples; j++) { const left = pointsLeft[Math.floor(j * t + j0)]; const right = pointsRight[Math.floor(j * t + j1)]; this.pointsData[0][j] = left * mix2 + this.pointsData[0][j - 1] * mix1; this.pointsData[1][j] = right * mix2 + this.pointsData[1][j - 1] * mix1; } for (let j = this.samples - 2; j >= 0; j--) { this.pointsData[0][j] = this.pointsData[0][j] * mix2 + this.pointsData[0][j + 1] * mix1; this.pointsData[1][j] = this.pointsData[1][j] * mix2 + this.pointsData[1][j + 1] * mix1; } for (let j = 0; j < this.samples; j++) { this.pointsData[0][j] *= scale; this.pointsData[1][j] *= scale; } if (!presetEquationRunner.preset.useWASM) { for (let j = 0; j < this.samples; j++) { const value1 = this.pointsData[0][j]; const value2 = this.pointsData[1][j]; mdVSWaveFrame.sample = j / (this.samples - 1); mdVSWaveFrame.value1 = value1; mdVSWaveFrame.value2 = value2; mdVSWaveFrame.x = 0.5 + value1; mdVSWaveFrame.y = 0.5 + value2; mdVSWaveFrame.r = frameR; mdVSWaveFrame.g = frameG; mdVSWaveFrame.b = frameB; mdVSWaveFrame.a = frameA; if (waveEqs.point_eqs !== "") { mdVSWaveFrame = presetEquationRunner.runWavePointEquations(this.index, mdVSWaveFrame); } const x = (mdVSWaveFrame.x * 2 - 1) * this.invAspectx; const y = (mdVSWaveFrame.y * -2 + 1) * this.invAspecty; const r = mdVSWaveFrame.r; const g = mdVSWaveFrame.g; const b = mdVSWaveFrame.b; const a = mdVSWaveFrame.a; this.positions[j * 3 + 0] = x; this.positions[j * 3 + 1] = y; this.positions[j * 3 + 2] = 0; this.colors[j * 4 + 0] = r; this.colors[j * 4 + 1] = g; this.colors[j * 4 + 2] = b; this.colors[j * 4 + 3] = a * alphaMult; } } else { const varPool = presetEquationRunner.preset.globalPools[`wavePerFrame${this.index}`]; for (let j = 0; j < this.samples; j++) { const value1 = this.pointsData[0][j]; const value2 = this.pointsData[1][j]; varPool.sample.value = j / (this.samples - 1); varPool.value1.value = value1; varPool.value2.value = value2; varPool.x.value = 0.5 + value1; varPool.y.value = 0.5 + value2; varPool.r.value = frameR; varPool.g.value = frameG; varPool.b.value = frameB; varPool.a.value = frameA; if (waveEqs.point_eqs) { presetEquationRunner.preset.waves[this.index].point_eqs(); } const x = (varPool.x.value * 2 - 1) * this.invAspectx; const y = (varPool.y.value * -2 + 1) * this.invAspecty; const r = varPool.r.value; const g = varPool.g.value; const b = varPool.b.value; const a = varPool.a.value; this.positions[j * 3 + 0] = x; this.positions[j * 3 + 1] = y; this.positions[j * 3 + 2] = 0; this.colors[j * 4 + 0] = r; this.colors[j * 4 + 1] = g; this.colors[j * 4 + 2] = b; this.colors[j * 4 + 3] = a * alphaMult; } } // this needs to be after per point (check fishbrain - witchcraft) if (!presetEquationRunner.preset.useWASM) { const mdvsUserKeysWave = presetEquationRunner.mdVSUserKeysWaves[this.index]; const mdVSNewFrameMapWave = _utils__WEBPACK_IMPORTED_MODULE_0__["default"].pick(mdVSWaveFrame, mdvsUserKeysWave); // eslint-disable-next-line no-param-reassign presetEquationRunner.mdVSFrameMapWaves[this.index] = mdVSNewFrameMapWave; } else { mdVSWaveFrame.usedots = usedots; mdVSWaveFrame.thick = baseVals.thick; mdVSWaveFrame.additive = baseVals.additive; } this.mdVSWaveFrame = mdVSWaveFrame; if (usedots === 0) { _waveUtils__WEBPACK_IMPORTED_MODULE_2__["default"].smoothWaveAndColor(this.positions, this.colors, this.smoothedPositions, this.smoothedColors, this.samples); } return true; } } return false; } drawCustomWaveform(blendProgress, timeArrayL, timeArrayR, freqArrayL, freqArrayR, globalVars, presetEquationRunner, waveEqs) { if (waveEqs && this.generateWaveform(timeArrayL, timeArrayR, freqArrayL, freqArrayR, globalVars, presetEquationRunner, waveEqs, blendProgress)) { this.gl.useProgram(this.shaderProgram); const waveUseDots = this.mdVSWaveFrame.usedots !== 0; const waveThick = this.mdVSWaveFrame.thick !== 0; const waveAdditive = this.mdVSWaveFrame.additive !== 0; let positions; let colors; let numVerts; if (!waveUseDots) { positions = this.smoothedPositions; colors = this.smoothedColors; numVerts = this.samples * 2 - 1; } else { positions = this.positions; colors = this.colors; numVerts = this.samples; } this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aPosLocation, 3, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aPosLocation); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.colorVertexBuf); this.gl.bufferData(this.gl.ARRAY_BUFFER, colors, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this.aColorLocation, 4, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this.aColorLocation); let instances = 1; if (waveUseDots) { if (waveThick) { this.gl.uniform1f(this.sizeLoc, 2 + (this.texsizeX >= 1024 ? 1 : 0)); } else { this.gl.uniform1f(this.sizeLoc, 1 + (this.texsizeX >= 1024 ? 1 : 0)); } } else { this.gl.uniform1f(this.sizeLoc, 1); if (waveThick) { instances = 4; } } if (waveAdditive) { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); } else { this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); } const drawMode = waveUseDots ? this.gl.POINTS : this.gl.LINE_STRIP; // TODO: use drawArraysInstanced for (let i = 0; i < instances; i++) { const offset = 2; if (i === 0) { this.gl.uniform2fv(this.thickOffsetLoc, [0, 0]); } else if (i === 1) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, 0]); } else if (i === 2) { this.gl.uniform2fv(this.thickOffsetLoc, [0, offset / this.texsizeY]); } else if (i === 3) { this.gl.uniform2fv(this.thickOffsetLoc, [offset / this.texsizeX, offset / this.texsizeY]); } this.gl.drawArrays(drawMode, 0, numVerts); } } } } /***/ }), /***/ "./src/rendering/waves/waveUtils.js": /*!******************************************!*\ !*** ./src/rendering/waves/waveUtils.js ***! \******************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return WaveUtils; }); class WaveUtils { /* eslint-disable no-param-reassign */ static smoothWave(positions, positionsSmoothed, nVertsIn, zCoord = false) { const c1 = -0.15; const c2 = 1.15; const c3 = 1.15; const c4 = -0.15; const invSum = 1.0 / (c1 + c2 + c3 + c4); let j = 0; let iBelow = 0; let iAbove; let iAbove2 = 1; for (let i = 0; i < nVertsIn - 1; i++) { iAbove = iAbove2; iAbove2 = Math.min(nVertsIn - 1, i + 2); for (let k = 0; k < 3; k++) { positionsSmoothed[j * 3 + k] = positions[i * 3 + k]; } if (zCoord) { for (let k = 0; k < 3; k++) { positionsSmoothed[(j + 1) * 3 + k] = (c1 * positions[iBelow * 3 + k] + c2 * positions[i * 3 + k] + c3 * positions[iAbove * 3 + k] + c4 * positions[iAbove2 * 3 + k]) * invSum; } } else { for (let k = 0; k < 2; k++) { positionsSmoothed[(j + 1) * 3 + k] = (c1 * positions[iBelow * 3 + k] + c2 * positions[i * 3 + k] + c3 * positions[iAbove * 3 + k] + c4 * positions[iAbove2 * 3 + k]) * invSum; } positionsSmoothed[(j + 1) * 3 + 2] = 0; } iBelow = i; j += 2; } for (let k = 0; k < 3; k++) { positionsSmoothed[j * 3 + k] = positions[(nVertsIn - 1) * 3 + k]; } } static smoothWaveAndColor(positions, colors, positionsSmoothed, colorsSmoothed, nVertsIn, zCoord = false) { const c1 = -0.15; const c2 = 1.15; const c3 = 1.15; const c4 = -0.15; const invSum = 1.0 / (c1 + c2 + c3 + c4); let j = 0; let iBelow = 0; let iAbove; let iAbove2 = 1; for (let i = 0; i < nVertsIn - 1; i++) { iAbove = iAbove2; iAbove2 = Math.min(nVertsIn - 1, i + 2); for (let k = 0; k < 3; k++) { positionsSmoothed[j * 3 + k] = positions[i * 3 + k]; } if (zCoord) { for (let k = 0; k < 3; k++) { positionsSmoothed[(j + 1) * 3 + k] = (c1 * positions[iBelow * 3 + k] + c2 * positions[i * 3 + k] + c3 * positions[iAbove * 3 + k] + c4 * positions[iAbove2 * 3 + k]) * invSum; } } else { for (let k = 0; k < 2; k++) { positionsSmoothed[(j + 1) * 3 + k] = (c1 * positions[iBelow * 3 + k] + c2 * positions[i * 3 + k] + c3 * positions[iAbove * 3 + k] + c4 * positions[iAbove2 * 3 + k]) * invSum; } positionsSmoothed[(j + 1) * 3 + 2] = 0; } for (let k = 0; k < 4; k++) { colorsSmoothed[j * 4 + k] = colors[i * 4 + k]; colorsSmoothed[(j + 1) * 4 + k] = colors[i * 4 + k]; } iBelow = i; j += 2; } for (let k = 0; k < 3; k++) { positionsSmoothed[j * 3 + k] = positions[(nVertsIn - 1) * 3 + k]; } for (let k = 0; k < 4; k++) { colorsSmoothed[j * 4 + k] = colors[(nVertsIn - 1) * 4 + k]; } } /* eslint-enable no-param-reassign */ } /***/ }), /***/ "./src/utils.js": /*!**********************!*\ !*** ./src/utils.js ***! \**********************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Utils; }); class Utils { static atan2(x, y) { let a = Math.atan2(x, y); if (a < 0) { a += 2 * Math.PI; } return a; } static cloneVars(vars) { return Object.assign({}, vars); } static range(start, end) { if (end === undefined) { return [...Array(start).keys()]; } return Array.from({ length: end - start }, (_, i) => i + start); } static pick(obj, keys) { const newObj = {}; for (let i = 0; i < keys.length; i++) { const key = keys[i]; newObj[key] = obj[key] || 0; } return newObj; } static omit(obj, keys) { const newObj = Object.assign({}, obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; delete newObj[key]; } return newObj; } static setWasm(wasmGlobals, obj, keys) { for (let i = 0; i < keys.length; i++) { const key = keys[i]; // eslint-disable-next-line no-param-reassign wasmGlobals[key].value = obj[key]; } } static pickWasm(wasmGlobals, keys) { const newObj = {}; for (let i = 0; i < keys.length; i++) { const key = keys[i]; newObj[key] = wasmGlobals[key].value; } return newObj; } } /***/ }), /***/ "./src/visualizer.js": /*!***************************!*\ !*** ./src/visualizer.js ***! \***************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Visualizer; }); /* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ "./node_modules/@babel/runtime/helpers/defineProperty.js"); /* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var eel_wasm__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! eel-wasm */ "./node_modules/eel-wasm/dist/src/index.js"); /* harmony import */ var eel_wasm__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(eel_wasm__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _assemblyscript_loader__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @assemblyscript/loader */ "./node_modules/@assemblyscript/loader/index.js"); /* harmony import */ var _audio_audioProcessor__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./audio/audioProcessor */ "./src/audio/audioProcessor.js"); /* harmony import */ var _rendering_renderer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./rendering/renderer */ "./src/rendering/renderer.js"); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./utils */ "./src/utils.js"); /* harmony import */ var _assemblyscript_presetFunctions_ts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./assemblyscript/presetFunctions.ts */ "./src/assemblyscript/presetFunctions.ts"); /* harmony import */ var _assemblyscript_presetFunctions_ts__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_assemblyscript_presetFunctions_ts__WEBPACK_IMPORTED_MODULE_6__); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default()(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } class Visualizer { constructor(audioContext, canvas, opts) { this.opts = opts; this.audio = new _audio_audioProcessor__WEBPACK_IMPORTED_MODULE_3__["default"](audioContext); const vizWidth = opts.width || 1200; const vizHeight = opts.height || 900; this.internalCanvas = document.createElement("canvas"); this.internalCanvas.width = vizWidth; this.internalCanvas.height = vizHeight; this.gl = this.internalCanvas.getContext("webgl2", { alpha: false, antialias: false, depth: false, stencil: false, premultipliedAlpha: false }); this.outputGl = canvas.getContext('2d'); this.baseValsDefaults = { decay: 0.98, gammaadj: 2, echo_zoom: 2, echo_alpha: 0, echo_orient: 0, red_blue: 0, brighten: 0, darken: 0, wrap: 1, darken_center: 0, solarize: 0, invert: 0, bmotionvectorson: 1, fshader: 0, b1n: 0, b2n: 0, b3n: 0, b1x: 1, b2x: 1, b3x: 1, b1ed: 0.25, wave_mode: 0, additivewave: 0, wave_dots: 0, wave_thick: 0, wave_a: 0.8, wave_scale: 1, wave_smoothing: 0.75, wave_mystery: 0, modwavealphabyvolume: 0, modwavealphastart: 0.75, modwavealphaend: 0.95, wave_r: 1, wave_g: 1, wave_b: 1, wave_x: 0.5, wave_y: 0.5, wave_brighten: 1, mv_x: 12, mv_y: 9, mv_dx: 0, mv_dy: 0, mv_l: 0.9, mv_r: 1, mv_g: 1, mv_b: 1, mv_a: 1, warpanimspeed: 1, warpscale: 1, zoomexp: 1, zoom: 1, rot: 0, cx: 0.5, cy: 0.5, dx: 0, dy: 0, warp: 1, sx: 1, sy: 1, ob_size: 0.01, ob_r: 0, ob_g: 0, ob_b: 0, ob_a: 0, ib_size: 0.01, ib_r: 0.25, ib_g: 0.25, ib_b: 0.25, ib_a: 0 }; this.shapeBaseValsDefaults = { enabled: 0, sides: 4, additive: 0, thickoutline: 0, textured: 0, num_inst: 1, tex_zoom: 1, tex_ang: 0, x: 0.5, y: 0.5, rad: 0.1, ang: 0, r: 1, g: 0, b: 0, a: 1, r2: 0, g2: 1, b2: 0, a2: 0, border_r: 1, border_g: 1, border_b: 1, border_a: 0.1 }; this.waveBaseValsDefaults = { enabled: 0, samples: 512, sep: 0, scaling: 1, smoothing: 0.5, r: 1, g: 1, b: 1, a: 1, spectrum: 0, usedots: 0, thick: 0, additive: 0 }; this.qs = _utils__WEBPACK_IMPORTED_MODULE_5__["default"].range(1, 33).map(x => `q${x}`); this.ts = _utils__WEBPACK_IMPORTED_MODULE_5__["default"].range(1, 9).map(x => `t${x}`); this.globalPerFrameVars = ["old_wave_mode", // globals "frame", "time", "fps", "bass", "bass_att", "mid", "mid_att", "treb", "treb_att", "meshx", "meshy", "aspectx", "aspecty", "pixelsx", "pixelsy", "rand_start", "rand_preset"]; this.globalPerPixelVars = [// globals "frame", "time", "fps", "bass", "bass_att", "mid", "mid_att", "treb", "treb_att", "meshx", "meshy", "aspectx", "aspecty", "pixelsx", "pixelsy", "rand_start", "rand_preset", // for pixel eqs "x", "y", "rad", "ang"]; this.globalShapeVars = [// globals "frame", "time", "fps", "bass", "bass_att", "mid", "mid_att", "treb", "treb_att", "meshx", "meshy", "aspectx", "aspecty", "pixelsx", "pixelsy", "rand_start", "rand_preset", // for shape eqs "instance"]; this.shapeBaseVars = ["x", "y", "rad", "ang", "r", "g", "b", "a", "r2", "g2", "b2", "a2", "border_r", "border_g", "border_b", "border_a", "thickoutline", "textured", "tex_zoom", "tex_ang", "additive"]; this.globalWaveVars = [// globals "frame", "time", "fps", "bass", "bass_att", "mid", "mid_att", "treb", "treb_att", "meshx", "meshy", "aspectx", "aspecty", "pixelsx", "pixelsy", "rand_start", "rand_preset", // for wave eqs "x", "y", "sample", "value1", "value2"]; this.renderer = new _rendering_renderer__WEBPACK_IMPORTED_MODULE_4__["default"](this.gl, this.audio, opts); } loseGLContext() { this.gl.getExtension("WEBGL_lose_context").loseContext(); this.outputGl = null; } connectAudio(audioNode) { this.audioNode = audioNode; this.audio.connectAudio(audioNode); } disconnectAudio(audioNode) { this.audio.disconnectAudio(audioNode); } // Override defaults, but only include variables in default map static overrideDefaultVars(baseValsDefaults, baseVals) { const combinedVals = {}; Object.keys(baseValsDefaults).forEach(key => { if (Object.prototype.hasOwnProperty.call(baseVals, key)) { combinedVals[key] = baseVals[key]; } else { combinedVals[key] = baseValsDefaults[key]; } }); return combinedVals; } createQVars() { const wasmVars = {}; this.qs.forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, 0); }); return wasmVars; } createTVars() { const wasmVars = {}; this.ts.forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, 0); }); return wasmVars; } createPerFramePool(baseVals) { const wasmVars = {}; Object.keys(this.baseValsDefaults).forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, baseVals[key]); }); this.globalPerFrameVars.forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, 0); }); return wasmVars; } createPerPixelPool(baseVals) { const wasmVars = {}; Object.keys(this.baseValsDefaults).forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, baseVals[key]); }); this.globalPerPixelVars.forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, 0); }); return wasmVars; } createCustomShapePerFramePool(baseVals) { const wasmVars = {}; Object.keys(this.shapeBaseValsDefaults).forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, baseVals[key]); }); this.globalShapeVars.forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, 0); }); return wasmVars; } createCustomWavePerFramePool(baseVals) { const wasmVars = {}; Object.keys(this.waveBaseValsDefaults).forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, baseVals[key]); }); this.globalWaveVars.forEach(key => { wasmVars[key] = new WebAssembly.Global({ value: "f64", mutable: true }, 0); }); return wasmVars; } static makeShapeResetPool(pool, variables, idx) { return variables.reduce((acc, variable) => { return _objectSpread(_objectSpread({}, acc), {}, { [`${variable}_${idx}`]: pool[variable] }); }, {}); } static base64ToArrayBuffer(base64) { var binaryString = window.atob(base64); var len = binaryString.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; } async loadPreset(presetMap, blendTime = 0) { const preset = JSON.parse(JSON.stringify(presetMap)); preset.baseVals = Visualizer.overrideDefaultVars(this.baseValsDefaults, preset.baseVals); for (let i = 0; i < preset.shapes.length; i++) { preset.shapes[i].baseVals = Visualizer.overrideDefaultVars(this.shapeBaseValsDefaults, preset.shapes[i].baseVals); } for (let i = 0; i < preset.waves.length; i++) { preset.waves[i].baseVals = Visualizer.overrideDefaultVars(this.waveBaseValsDefaults, preset.waves[i].baseVals); } const forceJS = preset.useJS && !this.opts.onlyUseWASM; if (Object.prototype.hasOwnProperty.call(preset, "init_eqs_eel") && !forceJS) { preset.useWASM = true; await this.loadWASMPreset(preset, blendTime); } else if (!this.opts.onlyUseWASM) { if (Object.prototype.hasOwnProperty.call(preset, "init_eqs_str")) { this.loadJSPreset(preset, blendTime); } else { console.warn("Tried to load a JS preset that doesn't have converted strings"); } } else { console.warn("Tried to load a preset that doesn't support WASM with onlyUseWASM on"); } } async loadWASMPreset(preset, blendTime) { const qWasmVars = this.createQVars(); const tWasmVars = this.createTVars(); const wasmVarPools = { perFrame: _objectSpread(_objectSpread({}, qWasmVars), this.createPerFramePool(preset.baseVals)), perVertex: _objectSpread(_objectSpread({}, qWasmVars), this.createPerPixelPool(preset.baseVals)) }; const wasmFunctions = { presetInit: { pool: "perFrame", code: preset.init_eqs_eel }, perFrame: { pool: "perFrame", code: preset.frame_eqs_eel } }; if (preset.pixel_eqs_eel !== "") { wasmFunctions.perPixel = { pool: "perVertex", code: preset.pixel_eqs_eel }; } for (let i = 0; i < preset.shapes.length; i++) { wasmVarPools[`shapePerFrame${i}`] = _objectSpread(_objectSpread(_objectSpread({}, qWasmVars), tWasmVars), this.createCustomShapePerFramePool(preset.shapes[i].baseVals)); if (preset.shapes[i].baseVals.enabled !== 0) { wasmFunctions[`shapes_${i}_init_eqs`] = { pool: `shapePerFrame${i}`, code: preset.shapes[i].init_eqs_eel }; wasmFunctions[`shapes_${i}_frame_eqs`] = { pool: `shapePerFrame${i}`, code: preset.shapes[i].frame_eqs_eel }; } } for (let i = 0; i < preset.waves.length; i++) { if (preset.waves[i].baseVals.enabled !== 0) { wasmVarPools[`wavePerFrame${i}`] = _objectSpread(_objectSpread(_objectSpread({}, qWasmVars), tWasmVars), this.createCustomWavePerFramePool(preset.waves[i].baseVals)); wasmFunctions[`waves_${i}_init_eqs`] = { pool: `wavePerFrame${i}`, code: preset.waves[i].init_eqs_eel }; wasmFunctions[`waves_${i}_frame_eqs`] = { pool: `wavePerFrame${i}`, code: preset.waves[i].frame_eqs_eel }; if (preset.waves[i].point_eqs_eel && preset.waves[i].point_eqs_eel !== "") { wasmFunctions[`waves_${i}_point_eqs`] = { pool: `wavePerFrame${i}`, code: preset.waves[i].point_eqs_eel }; } } } const mod = await Object(eel_wasm__WEBPACK_IMPORTED_MODULE_1__["loadModule"])({ pools: wasmVarPools, functions: wasmFunctions, eelVersion: preset.version || 2 }); // eel-wasm returns null if the function was empty const handleEmptyFunction = f => { return f ? f : () => {}; }; const presetFunctionsMod = await _assemblyscript_loader__WEBPACK_IMPORTED_MODULE_2__["default"].instantiate(Visualizer.base64ToArrayBuffer(_assemblyscript_presetFunctions_ts__WEBPACK_IMPORTED_MODULE_6___default()()), { pixelEqs: { perPixelEqs: handleEmptyFunction(mod.exports.perPixel) }, // For resetting pixel eq vars pixelVarPool: { warp: wasmVarPools.perVertex.warp, zoom: wasmVarPools.perVertex.zoom, zoomexp: wasmVarPools.perVertex.zoomexp, cx: wasmVarPools.perVertex.cx, cy: wasmVarPools.perVertex.cy, sx: wasmVarPools.perVertex.sx, sy: wasmVarPools.perVertex.sy, dx: wasmVarPools.perVertex.dx, dy: wasmVarPools.perVertex.dy, rot: wasmVarPools.perVertex.rot, x: wasmVarPools.perVertex.x, y: wasmVarPools.perVertex.y, ang: wasmVarPools.perVertex.ang, rad: wasmVarPools.perVertex.rad }, // For resetting qs/ts qVarPool: qWasmVars, tVarPool: tWasmVars, // For resetting shape vars shapePool0: Visualizer.makeShapeResetPool(wasmVarPools["shapePerFrame0"], this.shapeBaseVars, 0), shapePool1: Visualizer.makeShapeResetPool(wasmVarPools["shapePerFrame1"], this.shapeBaseVars, 1), shapePool2: Visualizer.makeShapeResetPool(wasmVarPools["shapePerFrame2"], this.shapeBaseVars, 2), shapePool3: Visualizer.makeShapeResetPool(wasmVarPools["shapePerFrame3"], this.shapeBaseVars, 3), console: { logi: value => { // eslint-disable-next-line no-console console.log("logi: " + value); }, logf: value => { // eslint-disable-next-line no-console console.log("logf: " + value); } }, env: { abort: () => {// No idea why we need this. } } }); preset.globalPools = wasmVarPools; preset.init_eqs = handleEmptyFunction(mod.exports.presetInit); preset.frame_eqs = handleEmptyFunction(mod.exports.perFrame); preset.save_qs = presetFunctionsMod.exports.saveQs; preset.restore_qs = presetFunctionsMod.exports.restoreQs; preset.save_ts = presetFunctionsMod.exports.saveTs; preset.restore_ts = presetFunctionsMod.exports.restoreTs; if (mod.exports.perPixel) { preset.pixel_eqs = mod.exports.perPixel; } preset.pixel_eqs_initialize_array = (meshWidth, meshHeight) => { const arrPtr = presetFunctionsMod.exports.createFloat32Array((meshWidth + 1) * (meshHeight + 1) * 2); preset.pixel_eqs_array = arrPtr; }; preset.pixel_eqs_get_array = () => { return presetFunctionsMod.exports.__getFloat32ArrayView(preset.pixel_eqs_array); }; preset.pixel_eqs_wasm = (...args) => presetFunctionsMod.exports.runPixelEquations(preset.pixel_eqs_array, ...args); for (let i = 0; i < preset.shapes.length; i++) { if (preset.shapes[i].baseVals.enabled !== 0) { preset.shapes[i].init_eqs = handleEmptyFunction(mod.exports[`shapes_${i}_init_eqs`]); // Not wrapped because we check if null in customShapes preset.shapes[i].frame_eqs = mod.exports[`shapes_${i}_frame_eqs`]; preset.shapes[i].frame_eqs_save = () => presetFunctionsMod.exports[`shape${i}_save`](); preset.shapes[i].frame_eqs_restore = () => presetFunctionsMod.exports[`shape${i}_restore`](); } } for (let i = 0; i < preset.waves.length; i++) { if (preset.waves[i].baseVals.enabled !== 0) { const wave = { init_eqs: handleEmptyFunction(mod.exports[`waves_${i}_init_eqs`]), frame_eqs: handleEmptyFunction(mod.exports[`waves_${i}_frame_eqs`]) }; if (preset.waves[i].point_eqs_eel && preset.waves[i].point_eqs_eel !== "") { // Not wrapped because we check if null in customWaves wave.point_eqs = mod.exports[`waves_${i}_point_eqs`]; } else { wave.point_eqs = ""; } preset.waves[i] = Object.assign({}, preset.waves[i], wave); } } this.renderer.loadPreset(preset, blendTime); } loadJSPreset(preset, blendTime) { // If init_eqs is already a function, it means we've already prepared the preset to run if (typeof preset.init_eqs !== "function") { /* eslint-disable no-param-reassign, no-new-func */ preset.init_eqs = new Function("a", `${preset.init_eqs_str} return a;`); preset.frame_eqs = new Function("a", `${preset.frame_eqs_str} return a;`); if (preset.pixel_eqs_str && preset.pixel_eqs_str !== "") { preset.pixel_eqs = new Function("a", `${preset.pixel_eqs_str} return a;`); } else { preset.pixel_eqs = ""; } for (let i = 0; i < preset.shapes.length; i++) { if (preset.shapes[i].baseVals.enabled !== 0) { preset.shapes[i] = Object.assign({}, preset.shapes[i], { init_eqs: new Function("a", `${preset.shapes[i].init_eqs_str} return a;`), frame_eqs: new Function("a", `${preset.shapes[i].frame_eqs_str} return a;`) }); } } for (let i = 0; i < preset.waves.length; i++) { if (preset.waves[i].baseVals.enabled !== 0) { const wave = { init_eqs: new Function("a", `${preset.waves[i].init_eqs_str} return a;`), frame_eqs: new Function("a", `${preset.waves[i].frame_eqs_str} return a;`) }; if (preset.waves[i].point_eqs_str && preset.waves[i].point_eqs_str !== "") { wave.point_eqs = new Function("a", `${preset.waves[i].point_eqs_str} return a;`); } else { wave.point_eqs = ""; } preset.waves[i] = Object.assign({}, preset.waves[i], wave); } } /* eslint-enable no-param-reassign, no-new-func */ } this.renderer.loadPreset(preset, blendTime); } loadExtraImages(imageData) { this.renderer.loadExtraImages(imageData); } setRendererSize(width, height, opts = {}) { this.internalCanvas.width = width; this.internalCanvas.height = height; this.renderer.setRendererSize(width, height, opts); } setInternalMeshSize(width, height) { this.renderer.setInternalMeshSize(width, height); } setOutputAA(useAA) { this.renderer.setOutputAA(useAA); } setCanvas(canvas) { this.outputGl = canvas.getContext('2d'); } render(opts) { const renderOutput = this.renderer.render(opts); if (this.outputGl) { this.outputGl.drawImage(this.internalCanvas, 0, 0); } return renderOutput; } launchSongTitleAnim(text) { this.renderer.launchSongTitleAnim(text); } toDataURL() { return this.renderer.toDataURL(); } warpBufferToDataURL() { return this.renderer.warpBufferToDataURL(); } } /***/ }) /******/ }); }); //# sourceMappingURL=butterchurn.js.map