@luma.gl/shadertools
Version:
Shader module system for luma.gl
61 lines (50 loc) • 2.9 kB
JavaScript
function testVariable(qualifier) {
return new RegExp("\\b".concat(qualifier, "[ \\t]+(\\w+[ \\t]+\\w+(\\[\\w+\\])?;)"), 'g');
}
const ES300_REPLACEMENTS = [[/^(#version[ \t]+(100|300[ \t]+es))?[ \t]*\n/, '#version 300 es\n'], [/\btexture(2D|2DProj|Cube)Lod(EXT)?\(/g, 'textureLod('], [/\btexture(2D|2DProj|Cube)(EXT)?\(/g, 'texture(']];
const ES300_VERTEX_REPLACEMENTS = [...ES300_REPLACEMENTS, [testVariable('attribute'), 'in $1'], [testVariable('varying'), 'out $1']];
const ES300_FRAGMENT_REPLACEMENTS = [...ES300_REPLACEMENTS, [testVariable('varying'), 'in $1']];
const ES100_REPLACEMENTS = [[/^#version[ \t]+300[ \t]+es/, '#version 100'], [/\btexture(2D|2DProj|Cube)Lod\(/g, 'texture$1LodEXT('], [/\btexture\(/g, 'texture2D('], [/\btextureLod\(/g, 'texture2DLodEXT(']];
const ES100_VERTEX_REPLACEMENTS = [...ES100_REPLACEMENTS, [testVariable('in'), 'attribute $1'], [testVariable('out'), 'varying $1']];
const ES100_FRAGMENT_REPLACEMENTS = [...ES100_REPLACEMENTS, [testVariable('in'), 'varying $1']];
const ES100_FRAGMENT_OUTPUT_NAME = 'gl_FragColor';
const ES300_FRAGMENT_OUTPUT_REGEX = /\bout[ \t]+vec4[ \t]+(\w+)[ \t]*;\n?/;
const REGEX_START_OF_MAIN = /void\s+main\s*\([^)]*\)\s*\{\n?/;
export default function transpileShader(source, targetGLSLVersion, isVertex) {
switch (targetGLSLVersion) {
case 300:
return isVertex ? convertShader(source, ES300_VERTEX_REPLACEMENTS) : convertFragmentShaderTo300(source);
case 100:
return isVertex ? convertShader(source, ES100_VERTEX_REPLACEMENTS) : convertFragmentShaderTo100(source);
default:
throw new Error("unknown GLSL version ".concat(targetGLSLVersion));
}
}
function convertShader(source, replacements) {
for (const [pattern, replacement] of replacements) {
source = source.replace(pattern, replacement);
}
return source;
}
function convertFragmentShaderTo300(source) {
source = convertShader(source, ES300_FRAGMENT_REPLACEMENTS);
const outputMatch = source.match(ES300_FRAGMENT_OUTPUT_REGEX);
if (outputMatch) {
const outputName = outputMatch[1];
source = source.replace(new RegExp("\\b".concat(ES100_FRAGMENT_OUTPUT_NAME, "\\b"), 'g'), outputName);
} else {
const outputName = 'fragmentColor';
source = source.replace(REGEX_START_OF_MAIN, match => "out vec4 ".concat(outputName, ";\n").concat(match)).replace(new RegExp("\\b".concat(ES100_FRAGMENT_OUTPUT_NAME, "\\b"), 'g'), outputName);
}
return source;
}
function convertFragmentShaderTo100(source) {
source = convertShader(source, ES100_FRAGMENT_REPLACEMENTS);
const outputMatch = source.match(ES300_FRAGMENT_OUTPUT_REGEX);
if (outputMatch) {
const outputName = outputMatch[1];
source = source.replace(ES300_FRAGMENT_OUTPUT_REGEX, '').replace(new RegExp("\\b".concat(outputName, "\\b"), 'g'), ES100_FRAGMENT_OUTPUT_NAME);
}
return source;
}
//# sourceMappingURL=transpile-shader.js.map