UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

134 lines (133 loc) 4.93 kB
import GLProgram from "./GLProgram.mjs"; var loopRegex = /for\s*?\(int\s*?_idx_\s*\=\s*([\w-]+)\;\s*_idx_\s*<\s*([\w-]+);\s*_idx_\s*\+\+\s*\)\s*\{\{([\s\S]+?)(?=\}\})\}\}/g; function unrollLoop(shaderStr, defines, lightsNumbers) { function replace(match, start, end, snippet) { var unroll = ""; if (isNaN(start)) { if (start in defines) { start = defines[start]; } else { start = lightNumberDefines[start]; } } if (isNaN(end)) { if (end in defines) { end = defines[end]; } else { end = lightNumberDefines[end]; } } for (var idx = parseInt(start); idx < parseInt(end); idx++) { unroll += "{" + snippet.replace(/float\s*\(\s*_idx_\s*\)/g, idx.toFixed(1)).replace(/_idx_/g, idx) + "}"; } return unroll; } var lightNumberDefines = {}; for (var lightType in lightsNumbers) { lightNumberDefines[lightType + "_COUNT"] = lightsNumbers[lightType]; } return shaderStr.replace(loopRegex, replace); } function getDefineCode(defines, lightsNumbers, enabledTextures) { var defineStr = []; if (lightsNumbers) { for (var lightType in lightsNumbers) { var count = lightsNumbers[lightType]; if (count > 0) { defineStr.push("#define " + lightType.toUpperCase() + "_COUNT " + count); } } } if (enabledTextures) { for (var i = 0; i < enabledTextures.length; i++) { var symbol = enabledTextures[i]; defineStr.push("#define " + symbol.toUpperCase() + "_ENABLED"); } } for (var symbol in defines) { var value = defines[symbol]; if (value === null) { defineStr.push("#define " + symbol); } else { defineStr.push("#define " + symbol + " " + value.toString()); } } return defineStr.join("\n"); } function getExtensionCode(exts) { var extensionStr = []; for (var i = 0; i < exts.length; i++) { extensionStr.push("#extension GL_" + exts[i] + " : enable"); } return extensionStr.join("\n"); } function getPrecisionCode(precision) { return ["precision", precision, "float"].join(" ") + ";\n" + ["precision", precision, "int"].join(" ") + ";\n" + ["precision", precision, "sampler2D"].join(" ") + ";\n"; } function ProgramManager(renderer) { this._renderer = renderer; this._cache = {}; } ProgramManager.prototype.getProgram = function(renderable, material, scene) { var cache = this._cache; var isSkinnedMesh = renderable.isSkinnedMesh && renderable.isSkinnedMesh(); var isInstancedMesh = renderable.isInstancedMesh && renderable.isInstancedMesh(); var key = "s" + material.shader.shaderID + "m" + material.getProgramKey(); if (scene) { key += "se" + scene.getProgramKey(renderable.lightGroup); } if (isSkinnedMesh) { key += ",sk" + renderable.joints.length; } if (isInstancedMesh) { key += ",is"; } var program = cache[key]; if (program) { return program; } var lightsNumbers = scene ? scene.getLightsNumbers(renderable.lightGroup) : {}; var renderer = this._renderer; var _gl = renderer.gl; var enabledTextures = material.getEnabledTextures(); var extraDefineCode = ""; if (isSkinnedMesh) { var skinDefines = { SKINNING: null, JOINT_COUNT: renderable.joints.length }; if (renderable.joints.length > renderer.getMaxJointNumber()) { skinDefines.USE_SKIN_MATRICES_TEXTURE = null; } extraDefineCode += "\n" + getDefineCode(skinDefines) + "\n"; } if (isInstancedMesh) { extraDefineCode += "\n#define INSTANCING\n"; } var vertexDefineStr = extraDefineCode + getDefineCode(material.vertexDefines, lightsNumbers, enabledTextures); var fragmentDefineStr = extraDefineCode + getDefineCode(material.fragmentDefines, lightsNumbers, enabledTextures); var vertexCode = vertexDefineStr + "\n" + material.shader.vertex; var extensions = [ "OES_standard_derivatives", "EXT_shader_texture_lod" ].filter(function(ext) { return renderer.getGLExtension(ext) != null; }); if (extensions.indexOf("EXT_shader_texture_lod") >= 0) { fragmentDefineStr += "\n#define SUPPORT_TEXTURE_LOD"; } if (extensions.indexOf("OES_standard_derivatives") >= 0) { fragmentDefineStr += "\n#define SUPPORT_STANDARD_DERIVATIVES"; } var fragmentCode = getExtensionCode(extensions) + "\n" + getPrecisionCode(material.precision) + "\n" + fragmentDefineStr + "\n" + material.shader.fragment; var finalVertexCode = unrollLoop(vertexCode, material.vertexDefines, lightsNumbers); var finalFragmentCode = unrollLoop(fragmentCode, material.fragmentDefines, lightsNumbers); var program = new GLProgram(); program.uniformSemantics = material.shader.uniformSemantics; program.attributes = material.shader.attributes; var errorMsg = program.buildProgram(_gl, material.shader, finalVertexCode, finalFragmentCode); program.__error = errorMsg; cache[key] = program; return program; }; export { ProgramManager as default };