UNPKG

@luma.gl/shadertools

Version:

Shader module system for luma.gl

315 lines (255 loc) 11.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.assembleShaders = assembleShaders; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _constants = require("./constants"); var _resolveModules = require("./resolve-modules"); var _platformDefines = require("./platform-defines"); var _injectShader = _interopRequireWildcard(require("./inject-shader")); var _transpileShader = _interopRequireDefault(require("./transpile-shader")); var _utils = require("../utils"); var _SHADER_TYPE; function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } var INJECT_SHADER_DECLARATIONS = "\n\n".concat(_injectShader.DECLARATION_INJECT_MARKER, "\n\n"); var SHADER_TYPE = (_SHADER_TYPE = {}, (0, _defineProperty2.default)(_SHADER_TYPE, _constants.VERTEX_SHADER, 'vertex'), (0, _defineProperty2.default)(_SHADER_TYPE, _constants.FRAGMENT_SHADER, 'fragment'), _SHADER_TYPE); var FRAGMENT_SHADER_PROLOGUE = "precision highp float;\n\n"; function assembleShaders(gl, opts) { var vs = opts.vs, fs = opts.fs; var modules = (0, _resolveModules.resolveModules)(opts.modules || []); return { gl: gl, vs: assembleShader(gl, Object.assign({}, opts, { source: vs, type: _constants.VERTEX_SHADER, modules: modules })), fs: assembleShader(gl, Object.assign({}, opts, { source: fs, type: _constants.FRAGMENT_SHADER, modules: modules })), getUniforms: assembleGetUniforms(modules) }; } function assembleShader(gl, _ref) { var id = _ref.id, source = _ref.source, type = _ref.type, modules = _ref.modules, _ref$defines = _ref.defines, defines = _ref$defines === void 0 ? {} : _ref$defines, _ref$hookFunctions = _ref.hookFunctions, hookFunctions = _ref$hookFunctions === void 0 ? [] : _ref$hookFunctions, _ref$inject = _ref.inject, inject = _ref$inject === void 0 ? {} : _ref$inject, _ref$transpileToGLSL = _ref.transpileToGLSL100, transpileToGLSL100 = _ref$transpileToGLSL === void 0 ? false : _ref$transpileToGLSL, _ref$prologue = _ref.prologue, prologue = _ref$prologue === void 0 ? true : _ref$prologue, log = _ref.log; (0, _utils.assert)(typeof source === 'string', 'shader source must be a string'); var isVertex = type === _constants.VERTEX_SHADER; var sourceLines = source.split('\n'); var glslVersion = 100; var versionLine = ''; var coreSource = source; if (sourceLines[0].indexOf('#version ') === 0) { glslVersion = 300; versionLine = sourceLines[0]; coreSource = sourceLines.slice(1).join('\n'); } else { versionLine = "#version ".concat(glslVersion); } var allDefines = {}; modules.forEach(function (module) { Object.assign(allDefines, module.getDefines()); }); Object.assign(allDefines, defines); var assembledSource = prologue ? "".concat(versionLine, "\n").concat(getShaderName({ id: id, source: source, type: type }), "\n").concat(getShaderType({ type: type }), "\n").concat((0, _platformDefines.getPlatformShaderDefines)(gl), "\n").concat((0, _platformDefines.getVersionDefines)(gl, glslVersion, !isVertex), "\n").concat(getApplicationDefines(allDefines), "\n").concat(isVertex ? '' : FRAGMENT_SHADER_PROLOGUE, "\n") : "".concat(versionLine, "\n"); var hookFunctionMap = normalizeHookFunctions(hookFunctions); var hookInjections = {}; var declInjections = {}; var mainInjections = {}; for (var key in inject) { var injection = typeof inject[key] === 'string' ? { injection: inject[key], order: 0 } : inject[key]; var match = key.match(/^(v|f)s:(#)?([\w-]+)$/); if (match) { var hash = match[2]; var name = match[3]; if (hash) { if (name === 'decl') { declInjections[key] = [injection]; } else { mainInjections[key] = [injection]; } } else { hookInjections[key] = [injection]; } } else { mainInjections[key] = [injection]; } } var _iterator = _createForOfIteratorHelper(modules), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var module = _step.value; if (log) { module.checkDeprecations(coreSource, log); } var moduleSource = module.getModuleSource(type, glslVersion); assembledSource += moduleSource; var injections = module.injections[type]; for (var _key in injections) { var _match = _key.match(/^(v|f)s:#([\w-]+)$/); if (_match) { var _name = _match[2]; var injectionType = _name === 'decl' ? declInjections : mainInjections; injectionType[_key] = injectionType[_key] || []; injectionType[_key].push(injections[_key]); } else { hookInjections[_key] = hookInjections[_key] || []; hookInjections[_key].push(injections[_key]); } } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } assembledSource += INJECT_SHADER_DECLARATIONS; assembledSource = (0, _injectShader.default)(assembledSource, type, declInjections); assembledSource += getHookFunctions(hookFunctionMap[type], hookInjections); assembledSource += coreSource; assembledSource = (0, _injectShader.default)(assembledSource, type, mainInjections); assembledSource = (0, _transpileShader.default)(assembledSource, transpileToGLSL100 ? 100 : glslVersion, isVertex); return assembledSource; } function assembleGetUniforms(modules) { return function getUniforms(opts) { var uniforms = {}; var _iterator2 = _createForOfIteratorHelper(modules), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var module = _step2.value; var moduleUniforms = module.getUniforms(opts, uniforms); Object.assign(uniforms, moduleUniforms); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } return uniforms; }; } function getShaderType(_ref2) { var type = _ref2.type; return "\n#define SHADER_TYPE_".concat(SHADER_TYPE[type].toUpperCase(), "\n"); } function getShaderName(_ref3) { var id = _ref3.id, source = _ref3.source, type = _ref3.type; var injectShaderName = id && typeof id === 'string' && source.indexOf('SHADER_NAME') === -1; return injectShaderName ? "\n#define SHADER_NAME ".concat(id, "_").concat(SHADER_TYPE[type], "\n\n") : ''; } function getApplicationDefines() { var defines = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var count = 0; var sourceText = ''; for (var define in defines) { if (count === 0) { sourceText += '\n// APPLICATION DEFINES\n'; } count++; var value = defines[define]; if (value || Number.isFinite(value)) { sourceText += "#define ".concat(define.toUpperCase(), " ").concat(defines[define], "\n"); } } if (count === 0) { sourceText += '\n'; } return sourceText; } function getHookFunctions(hookFunctions, hookInjections) { var result = ''; for (var hookName in hookFunctions) { var hookFunction = hookFunctions[hookName]; result += "void ".concat(hookFunction.signature, " {\n"); if (hookFunction.header) { result += " ".concat(hookFunction.header); } if (hookInjections[hookName]) { var injections = hookInjections[hookName]; injections.sort(function (a, b) { return a.order - b.order; }); var _iterator3 = _createForOfIteratorHelper(injections), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var injection = _step3.value; result += " ".concat(injection.injection, "\n"); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } if (hookFunction.footer) { result += " ".concat(hookFunction.footer); } result += '}\n'; } return result; } function normalizeHookFunctions(hookFunctions) { var result = { vs: {}, fs: {} }; hookFunctions.forEach(function (hook) { var opts; if (typeof hook !== 'string') { opts = hook; hook = opts.hook; } else { opts = {}; } hook = hook.trim(); var _hook$split = hook.split(':'), _hook$split2 = (0, _slicedToArray2.default)(_hook$split, 2), stage = _hook$split2[0], signature = _hook$split2[1]; var name = hook.replace(/\(.+/, ''); result[stage][name] = Object.assign(opts, { signature: signature }); }); return result; } //# sourceMappingURL=assemble-shaders.js.map