UNPKG

laya-coreui-es

Version:

laya核心库、ui库es版本,剔除了媒体、TTF等功能。基于 LayaAir-release_2.12.0 修改

288 lines (287 loc) 13.3 kB
import { LayaGL } from "../../layagl/LayaGL"; import { Shader } from "../shader/Shader"; import { InlcudeFile } from "./InlcudeFile"; import { ShaderNode } from "./ShaderNode"; export class ShaderCompile { static __init__() { var gl = LayaGL.instance; ShaderCompile.shaderParamsMap = { "float": gl.FLOAT, "int": gl.INT, "bool": gl.BOOL, "vec2": gl.FLOAT_VEC2, "vec3": gl.FLOAT_VEC3, "vec4": gl.FLOAT_VEC4, "ivec2": gl.INT_VEC2, "ivec3": gl.INT_VEC3, "ivec4": gl.INT_VEC4, "bvec2": gl.BOOL_VEC2, "bvec3": gl.BOOL_VEC3, "bvec4": gl.BOOL_VEC4, "mat2": gl.FLOAT_MAT2, "mat3": gl.FLOAT_MAT3, "mat4": gl.FLOAT_MAT4, "sampler2D": gl.SAMPLER_2D, "samplerCube": gl.SAMPLER_CUBE }; } static _parseOne(attributes, uniforms, words, i, word, b) { var one = { type: ShaderCompile.shaderParamsMap[words[i + 1]], name: words[i + 2], size: isNaN(parseInt(words[i + 3])) ? 1 : parseInt(words[i + 3]) }; if (b) { if (word == "attribute") { attributes.push(one); } else { uniforms.push(one); } } if (words[i + 3] == ':') { one.type = words[i + 4]; i += 2; } i += 2; return i; } static addInclude(fileName, txt) { if (!txt || txt.length === 0) throw new Error("add shader include file err:" + fileName); if (ShaderCompile.includes[fileName]) throw new Error("add shader include file err, has add:" + fileName); ShaderCompile.includes[fileName] = new InlcudeFile(txt); } static preGetParams(vs, ps) { var text = [vs, ps]; var result = {}; var attributes = []; var uniforms = []; var definesInfo = {}; var definesName = {}; result.attributes = attributes; result.uniforms = uniforms; result.defines = definesInfo; var i, n; for (var s = 0; s < 2; s++) { text[s] = text[s].replace(ShaderCompile._removeAnnotation, ""); var words = text[s].match(ShaderCompile._reg); var tempelse; for (i = 0, n = words.length; i < n; i++) { var word = words[i]; if (word != "attribute" && word != "uniform") { if (word == "#define") { word = words[++i]; definesName[word] = 1; continue; } else if (word == "#ifdef") { tempelse = words[++i]; var def = definesInfo[tempelse] = definesInfo[tempelse] || []; for (i++; i < n; i++) { word = words[i]; if (word != "attribute" && word != "uniform") { if (word == "#else") { for (i++; i < n; i++) { word = words[i]; if (word != "attribute" && word != "uniform") { if (word == "#endif") { break; } continue; } i = ShaderCompile._parseOne(attributes, uniforms, words, i, word, !definesName[tempelse]); } } continue; } i = ShaderCompile._parseOne(attributes, uniforms, words, i, word, !!definesName[tempelse]); } } continue; } i = ShaderCompile._parseOne(attributes, uniforms, words, i, word, true); } } return result; } static splitToWords(str, block) { var out = []; var c; var ofs = -1; var word; for (var i = 0, n = str.length; i < n; i++) { c = str.charAt(i); if (" \t=+-*/&%!<>()'\",;".indexOf(c) >= 0) { if (ofs >= 0 && (i - ofs) > 1) { word = str.substr(ofs, i - ofs); out.push(word); } if (c == '"' || c == "'") { var ofs2 = str.indexOf(c, i + 1); if (ofs2 < 0) { throw "Sharder err:" + str; } out.push(str.substr(i + 1, ofs2 - i - 1)); i = ofs2; ofs = -1; continue; } if (c == '(' && block && out.length > 0) { word = out[out.length - 1] + ";"; if ("vec4;main;".indexOf(word) < 0) block.useFuns += word; } ofs = -1; continue; } if (ofs < 0) ofs = i; } if (ofs < n && (n - ofs) > 1) { word = str.substr(ofs, n - ofs); out.push(word); } return out; } constructor(vs, ps, nameMap) { this.defs = {}; let _this = this; function _compile(script) { script = script.replace(ShaderCompile._clearCR, ""); var includefiles = []; var top = new ShaderNode(includefiles); _this._compileToTree(top, script.split('\n'), 0, includefiles, _this.defs); return top; } var startTime = Date.now(); this._VS = _compile(vs); this._PS = _compile(ps); this._nameMap = nameMap; if ((Date.now() - startTime) > 2) console.log("ShaderCompile use time:" + (Date.now() - startTime) + " size:" + vs.length + "/" + ps.length); } _compileToTree(parent, lines, start, includefiles, defs) { var node, preNode; var text, name, fname; var ofs, words, noUseNode; var i, n, j; for (i = start; i < lines.length; i++) { text = lines[i]; if (text.length < 1) continue; ofs = text.indexOf("//"); if (ofs === 0) continue; if (ofs >= 0) text = text.substr(0, ofs); node = noUseNode || new ShaderNode(includefiles); noUseNode = null; node.text = text; node.noCompile = true; if ((ofs = text.indexOf("#")) >= 0) { name = "#"; for (j = ofs + 1, n = text.length; j < n; j++) { var c = text.charAt(j); if (c === ' ' || c === '\t' || c === '?') break; name += c; } node.name = name; switch (name) { case "#ifdef": case "#ifndef": node.src = text; node.noCompile = text.match(/[!&|()=<>]/) != null; if (!node.noCompile) { words = text.replace(/^\s*/, '').split(/\s+/); node.setCondition(words[1], name === "#ifdef" ? ShaderCompile.IFDEF_YES : ShaderCompile.IFDEF_ELSE); node.text = "//" + node.text; } else { console.log("function():Boolean{return " + text.substr(ofs + node.name.length) + "}"); } node.setParent(parent); parent = node; if (defs) { words = text.substr(j).split(ShaderCompile._splitToWordExps3); for (j = 0; j < words.length; j++) { text = words[j]; text.length && (defs[text] = true); } } continue; case "#if": node.src = text; node.noCompile = true; node.setParent(parent); parent = node; if (defs) { words = text.substr(j).split(ShaderCompile._splitToWordExps3); for (j = 0; j < words.length; j++) { text = words[j]; text.length && text != "defined" && (defs[text] = true); } } continue; case "#else": node.src = text; parent = parent.parent; preNode = parent.childs[parent.childs.length - 1]; node.noCompile = preNode.noCompile; if (!node.noCompile) { node.condition = preNode.condition; node.conditionType = preNode.conditionType == ShaderCompile.IFDEF_YES ? ShaderCompile.IFDEF_ELSE : ShaderCompile.IFDEF_YES; node.text = "//" + node.text + " " + preNode.text + " " + node.conditionType; } node.setParent(parent); parent = node; continue; case "#endif": parent = parent.parent; preNode = parent.childs[parent.childs.length - 1]; node.noCompile = preNode.noCompile; if (!node.noCompile) { node.text = "//" + node.text; } node.setParent(parent); continue; case "#include": words = ShaderCompile.splitToWords(text, null); var inlcudeFile = ShaderCompile.includes[words[1]]; if (!inlcudeFile) { throw "ShaderCompile error no this include file:" + words[1]; } if ((ofs = words[0].indexOf("?")) < 0) { node.setParent(parent); text = inlcudeFile.getWith(words[2] == 'with' ? words[3] : null); this._compileToTree(node, text.split('\n'), 0, includefiles, defs); node.text = ""; continue; } node.setCondition(words[0].substr(ofs + 1), ShaderCompile.IFDEF_YES); node.text = inlcudeFile.getWith(words[2] == 'with' ? words[3] : null); break; case "#import": words = ShaderCompile.splitToWords(text, null); fname = words[1]; includefiles.push({ node: node, file: ShaderCompile.includes[fname], ofs: node.text.length }); continue; } } else { preNode = parent.childs[parent.childs.length - 1]; if (preNode && !preNode.name) { includefiles.length > 0 && ShaderCompile.splitToWords(text, preNode); noUseNode = node; preNode.text += "\n" + text; continue; } includefiles.length > 0 && ShaderCompile.splitToWords(text, node); } node.setParent(parent); } } createShader(define, shaderName, createShader, bindAttrib) { var defMap = {}; var defineStr = ""; if (define) { for (var i in define) { defineStr += "#define " + i + "\n"; defMap[i] = true; } } var vs = this._VS.toscript(defMap, []); var ps = this._PS.toscript(defMap, []); return (createShader || Shader.create)(defineStr + vs.join('\n'), defineStr + ps.join('\n'), shaderName, this._nameMap, bindAttrib); } } ShaderCompile.IFDEF_NO = 0; ShaderCompile.IFDEF_YES = 1; ShaderCompile.IFDEF_ELSE = 2; ShaderCompile.IFDEF_PARENT = 3; ShaderCompile._removeAnnotation = new RegExp("(/\\*([^*]|[\\r\\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/)|(//.*)", "g"); ShaderCompile._reg = new RegExp("(\".*\")|('.*')|([#\\w\\*-\\.+/()=<>{}\\\\]+)|([,;:\\\\])", "g"); ShaderCompile._splitToWordExps = new RegExp("[(\".*\")]+|[('.*')]+|([ \\t=\\+\\-*/&%!<>!%\(\),;])", "g"); ShaderCompile.includes = {}; ShaderCompile._clearCR = new RegExp("\r", "g"); ShaderCompile._splitToWordExps3 = new RegExp("[ \\t=\\+\\-*/&%!<>!%\(\),;\\|]", "g");