123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- define([
- '../Core/defaultValue',
- '../Core/defined',
- '../Core/DeveloperError',
- '../Shaders/Builtin/CzmBuiltins',
- './AutomaticUniforms'
- ], function(
- defaultValue,
- defined,
- DeveloperError,
- CzmBuiltins,
- AutomaticUniforms) {
- "use strict";
- function removeComments(source) {
- return source.replace(/\/\*\*[\s\S]*?\*\//gm, function(match) {
-
- var numberOfLines = match.match(/\n/gm).length;
- var replacement = '';
- for (var lineNumber = 0; lineNumber < numberOfLines; ++lineNumber) {
- replacement += '\n';
- }
- return replacement;
- });
- }
- function getDependencyNode(name, glslSource, nodes) {
- var dependencyNode;
-
- for (var i = 0; i < nodes.length; ++i) {
- if (nodes[i].name === name) {
- dependencyNode = nodes[i];
- }
- }
- if (!defined(dependencyNode)) {
-
-
- glslSource = removeComments(glslSource);
-
- dependencyNode = {
- name : name,
- glslSource : glslSource,
- dependsOn : [],
- requiredBy : [],
- evaluated : false
- };
- nodes.push(dependencyNode);
- }
- return dependencyNode;
- }
- function generateDependencies(currentNode, dependencyNodes) {
- if (currentNode.evaluated) {
- return;
- }
- currentNode.evaluated = true;
-
- var czmMatches = currentNode.glslSource.match(/\bczm_[a-zA-Z0-9_]*/g);
- if (defined(czmMatches) && czmMatches !== null) {
-
- czmMatches = czmMatches.filter(function(elem, pos) {
- return czmMatches.indexOf(elem) === pos;
- });
- czmMatches.forEach(function(element) {
- if (element !== currentNode.name && ShaderSource._czmBuiltinsAndUniforms.hasOwnProperty(element)) {
- var referencedNode = getDependencyNode(element, ShaderSource._czmBuiltinsAndUniforms[element], dependencyNodes);
- currentNode.dependsOn.push(referencedNode);
- referencedNode.requiredBy.push(currentNode);
-
- generateDependencies(referencedNode, dependencyNodes);
- }
- });
- }
- }
- function sortDependencies(dependencyNodes) {
- var nodesWithoutIncomingEdges = [];
- var allNodes = [];
- while (dependencyNodes.length > 0) {
- var node = dependencyNodes.pop();
- allNodes.push(node);
- if (node.requiredBy.length === 0) {
- nodesWithoutIncomingEdges.push(node);
- }
- }
- while (nodesWithoutIncomingEdges.length > 0) {
- var currentNode = nodesWithoutIncomingEdges.shift();
- dependencyNodes.push(currentNode);
- for (var i = 0; i < currentNode.dependsOn.length; ++i) {
-
- var referencedNode = currentNode.dependsOn[i];
- var index = referencedNode.requiredBy.indexOf(currentNode);
- referencedNode.requiredBy.splice(index, 1);
-
- if (referencedNode.requiredBy.length === 0) {
- nodesWithoutIncomingEdges.push(referencedNode);
- }
- }
- }
-
- var badNodes = [];
- for (var j = 0; j < allNodes.length; ++j) {
- if (allNodes[j].requiredBy.length !== 0) {
- badNodes.push(allNodes[j]);
- }
- }
- if (badNodes.length !== 0) {
- var message = 'A circular dependency was found in the following built-in functions/structs/constants: \n';
- for (j = 0; j < badNodes.length; ++j) {
- message = message + badNodes[j].name + '\n';
- }
- throw new DeveloperError(message);
- }
- }
- function getBuiltinsAndAutomaticUniforms(shaderSource) {
-
- var dependencyNodes = [];
- var root = getDependencyNode('main', shaderSource, dependencyNodes);
- generateDependencies(root, dependencyNodes);
- sortDependencies(dependencyNodes);
-
-
- var builtinsSource = '';
- for (var i = dependencyNodes.length - 1; i >= 0; --i) {
- builtinsSource = builtinsSource + dependencyNodes[i].glslSource + '\n';
- }
- return builtinsSource.replace(root.glslSource, '');
- }
- function combineShader(shaderSource, isFragmentShader) {
- var i;
- var length;
-
- var combinedSources = '';
- var sources = shaderSource.sources;
- if (defined(sources)) {
- for (i = 0, length = sources.length; i < length; ++i) {
-
- combinedSources += '\n#line 0\n' + sources[i];
- }
- }
- combinedSources = removeComments(combinedSources);
-
- var version;
- combinedSources = combinedSources.replace(/#version\s+(.*?)\n/gm, function(match, group1) {
- if (defined(version) && version !== group1) {
- throw new DeveloperError('inconsistent versions found: ' + version + ' and ' + group1);
- }
-
- version = group1;
-
-
-
-
- return '\n';
- });
-
- var pickColorQualifier = shaderSource.pickColorQualifier;
- if (defined(pickColorQualifier)) {
- combinedSources = combinedSources.replace(/void\s+main\s*\(\s*(?:void)?\s*\)/g, 'void czm_old_main()');
- combinedSources += '\
- \n' + pickColorQualifier + ' vec4 czm_pickColor;\n\
- void main()\n\
- {\n\
- czm_old_main();\n\
- if (gl_FragColor.a == 0.0) {\n\
- discard;\n\
- }\n\
- gl_FragColor = czm_pickColor;\n\
- }';
- }
-
- var result = '';
-
-
- if (defined(version)) {
- result = '#version ' + version;
- }
- if (isFragmentShader) {
- result += '\
- #ifdef GL_FRAGMENT_PRECISION_HIGH\n\
- precision highp float;\n\
- #else\n\
- precision mediump float;\n\
- #endif\n\n';
- }
-
- var defines = shaderSource.defines;
- if (defined(defines)) {
- for (i = 0, length = defines.length; i < length; ++i) {
- var define = defines[i];
- if (define.length !== 0) {
- result += '#define ' + define + '\n';
- }
- }
- }
-
- if (shaderSource.includeBuiltIns) {
- result += getBuiltinsAndAutomaticUniforms(combinedSources);
- }
-
- result += '\n#line 0\n';
-
- result += combinedSources;
- return result;
- }
-
- var ShaderSource = function(options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- var pickColorQualifier = options.pickColorQualifier;
-
- if (defined(pickColorQualifier) && pickColorQualifier !== 'uniform' && pickColorQualifier !== 'varying') {
- throw new DeveloperError('options.pickColorQualifier must be \'uniform\' or \'varying\'.');
- }
-
- this.defines = defined(options.defines) ? options.defines.slice(0) : [];
- this.sources = defined(options.sources) ? options.sources.slice(0) : [];
- this.pickColorQualifier = pickColorQualifier;
- this.includeBuiltIns = defaultValue(options.includeBuiltIns, true);
- };
- ShaderSource.prototype.clone = function() {
- return new ShaderSource({
- sources : this.sources,
- defines : this.defines,
- pickColorQuantifier : this.pickColorQualifier,
- includeBuiltIns : this.includeBuiltIns
- });
- };
-
- ShaderSource.prototype.createCombinedVertexShader = function() {
- return combineShader(this, false);
- };
-
- ShaderSource.prototype.createCombinedFragmentShader = function() {
- return combineShader(this, true);
- };
-
- ShaderSource._czmBuiltinsAndUniforms = {};
-
- for ( var builtinName in CzmBuiltins) {
- if (CzmBuiltins.hasOwnProperty(builtinName)) {
- ShaderSource._czmBuiltinsAndUniforms[builtinName] = CzmBuiltins[builtinName];
- }
- }
- for ( var uniformName in AutomaticUniforms) {
- if (AutomaticUniforms.hasOwnProperty(uniformName)) {
- var uniform = AutomaticUniforms[uniformName];
- if (typeof uniform.getDeclaration === 'function') {
- ShaderSource._czmBuiltinsAndUniforms[uniformName] = uniform.getDeclaration(uniformName);
- }
- }
- }
- return ShaderSource;
- });
|