@luma.gl/shadertools
Version:
Shader module system for luma.gl
315 lines (255 loc) • 11.7 kB
JavaScript
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
;