@luma.gl/shadertools
Version:
Shader module system for luma.gl
93 lines (74 loc) • 2.69 kB
JavaScript
import { MODULE_INJECTORS_VS, MODULE_INJECTORS_FS } from '../modules/module-injectors';
import { VERTEX_SHADER, FRAGMENT_SHADER } from './constants';
import { assert } from '../utils';
const MODULE_INJECTORS = {
[VERTEX_SHADER]: MODULE_INJECTORS_VS,
[FRAGMENT_SHADER]: MODULE_INJECTORS_FS
};
export const DECLARATION_INJECT_MARKER = '__LUMA_INJECT_DECLARATIONS__';
const REGEX_START_OF_MAIN = /void\s+main\s*\([^)]*\)\s*\{\n?/;
const REGEX_END_OF_MAIN = /}\n?[^{}]*$/;
const fragments = [];
export default function injectShader(source, type, inject) {
let injectStandardStubs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
const isVertex = type === VERTEX_SHADER;
for (const key in inject) {
const fragmentData = inject[key];
fragmentData.sort((a, b) => a.order - b.order);
fragments.length = fragmentData.length;
for (let i = 0, len = fragmentData.length; i < len; ++i) {
fragments[i] = fragmentData[i].injection;
}
const fragmentString = "".concat(fragments.join('\n'), "\n");
switch (key) {
case 'vs:#decl':
if (isVertex) {
source = source.replace(DECLARATION_INJECT_MARKER, fragmentString);
}
break;
case 'vs:#main-start':
if (isVertex) {
source = source.replace(REGEX_START_OF_MAIN, match => match + fragmentString);
}
break;
case 'vs:#main-end':
if (isVertex) {
source = source.replace(REGEX_END_OF_MAIN, match => fragmentString + match);
}
break;
case 'fs:#decl':
if (!isVertex) {
source = source.replace(DECLARATION_INJECT_MARKER, fragmentString);
}
break;
case 'fs:#main-start':
if (!isVertex) {
source = source.replace(REGEX_START_OF_MAIN, match => match + fragmentString);
}
break;
case 'fs:#main-end':
if (!isVertex) {
source = source.replace(REGEX_END_OF_MAIN, match => fragmentString + match);
}
break;
default:
source = source.replace(key, match => match + fragmentString);
}
}
source = source.replace(DECLARATION_INJECT_MARKER, '');
if (injectStandardStubs) {
source = source.replace(/\}\s*$/, match => match + MODULE_INJECTORS[type]);
}
return source;
}
export function combineInjects(injects) {
const result = {};
assert(Array.isArray(injects) && injects.length > 1);
injects.forEach(inject => {
for (const key in inject) {
result[key] = result[key] ? "".concat(result[key], "\n").concat(inject[key]) : inject[key];
}
});
return result;
}
//# sourceMappingURL=inject-shader.js.map