Material.js 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  1. /*global define*/
  2. define([
  3. '../Core/Cartesian2',
  4. '../Core/clone',
  5. '../Core/Color',
  6. '../Core/combine',
  7. '../Core/createGuid',
  8. '../Core/defaultValue',
  9. '../Core/defined',
  10. '../Core/defineProperties',
  11. '../Core/destroyObject',
  12. '../Core/DeveloperError',
  13. '../Core/isArray',
  14. '../Core/loadImage',
  15. '../Core/Matrix2',
  16. '../Core/Matrix3',
  17. '../Core/Matrix4',
  18. '../Renderer/CubeMap',
  19. '../Renderer/Texture',
  20. '../Shaders/Materials/BumpMapMaterial',
  21. '../Shaders/Materials/CheckerboardMaterial',
  22. '../Shaders/Materials/DotMaterial',
  23. '../Shaders/Materials/FadeMaterial',
  24. '../Shaders/Materials/GridMaterial',
  25. '../Shaders/Materials/NormalMapMaterial',
  26. '../Shaders/Materials/PolylineArrowMaterial',
  27. '../Shaders/Materials/PolylineGlowMaterial',
  28. '../Shaders/Materials/PolylineOutlineMaterial',
  29. '../Shaders/Materials/RimLightingMaterial',
  30. '../Shaders/Materials/StripeMaterial',
  31. '../Shaders/Materials/Water',
  32. '../ThirdParty/when'
  33. ], function(
  34. Cartesian2,
  35. clone,
  36. Color,
  37. combine,
  38. createGuid,
  39. defaultValue,
  40. defined,
  41. defineProperties,
  42. destroyObject,
  43. DeveloperError,
  44. isArray,
  45. loadImage,
  46. Matrix2,
  47. Matrix3,
  48. Matrix4,
  49. CubeMap,
  50. Texture,
  51. BumpMapMaterial,
  52. CheckerboardMaterial,
  53. DotMaterial,
  54. FadeMaterial,
  55. GridMaterial,
  56. NormalMapMaterial,
  57. PolylineArrowMaterial,
  58. PolylineGlowMaterial,
  59. PolylineOutlineMaterial,
  60. RimLightingMaterial,
  61. StripeMaterial,
  62. WaterMaterial,
  63. when) {
  64. "use strict";
  65. /**
  66. * A Material defines surface appearance through a combination of diffuse, specular,
  67. * normal, emission, and alpha components. These values are specified using a
  68. * JSON schema called Fabric which gets parsed and assembled into glsl shader code
  69. * behind-the-scenes. Check out the {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|wiki page}
  70. * for more details on Fabric.
  71. * <br /><br />
  72. * <style type="text/css">
  73. * #materialDescriptions code {
  74. * font-weight: normal;
  75. * font-family: Consolas, 'Lucida Console', Monaco, monospace;
  76. * color: #A35A00;
  77. * }
  78. * #materialDescriptions ul, #materialDescriptions ul ul {
  79. * list-style-type: none;
  80. * }
  81. * #materialDescriptions ul ul {
  82. * margin-bottom: 10px;
  83. * }
  84. * #materialDescriptions ul ul li {
  85. * font-weight: normal;
  86. * color: #000000;
  87. * text-indent: -2em;
  88. * margin-left: 2em;
  89. * }
  90. * #materialDescriptions ul li {
  91. * font-weight: bold;
  92. * color: #0053CF;
  93. * }
  94. * </style>
  95. *
  96. * Base material types and their uniforms:
  97. * <div id='materialDescriptions'>
  98. * <ul>
  99. * <li>Color</li>
  100. * <ul>
  101. * <li><code>color</code>: rgba color object.</li>
  102. * </ul>
  103. * <li>Image</li>
  104. * <ul>
  105. * <li><code>image</code>: path to image.</li>
  106. * <li><code>repeat</code>: Object with x and y values specifying the number of times to repeat the image.</li>
  107. * </ul>
  108. * <li>DiffuseMap</li>
  109. * <ul>
  110. * <li><code>image</code>: path to image.</li>
  111. * <li><code>channels</code>: Three character string containing any combination of r, g, b, and a for selecting the desired image channels.</li>
  112. * <li><code>repeat</code>: Object with x and y values specifying the number of times to repeat the image.</li>
  113. * </ul>
  114. * <li>AlphaMap</li>
  115. * <ul>
  116. * <li><code>image</code>: path to image.</li>
  117. * <li><code>channel</code>: One character string containing r, g, b, or a for selecting the desired image channel. </li>
  118. * <li><code>repeat</code>: Object with x and y values specifying the number of times to repeat the image.</li>
  119. * </ul>
  120. * <li>SpecularMap</li>
  121. * <ul>
  122. * <li><code>image</code>: path to image.</li>
  123. * <li><code>channel</code>: One character string containing r, g, b, or a for selecting the desired image channel. </li>
  124. * <li><code>repeat</code>: Object with x and y values specifying the number of times to repeat the image.</li>
  125. * </ul>
  126. * <li>EmissionMap</li>
  127. * <ul>
  128. * <li><code>image</code>: path to image.</li>
  129. * <li><code>channels</code>: Three character string containing any combination of r, g, b, and a for selecting the desired image channels. </li>
  130. * <li><code>repeat</code>: Object with x and y values specifying the number of times to repeat the image.</li>
  131. * </ul>
  132. * <li>BumpMap</li>
  133. * <ul>
  134. * <li><code>image</code>: path to image.</li>
  135. * <li><code>channel</code>: One character string containing r, g, b, or a for selecting the desired image channel. </li>
  136. * <li><code>repeat</code>: Object with x and y values specifying the number of times to repeat the image.</li>
  137. * <li><code>strength</code>: Bump strength value between 0.0 and 1.0 where 0.0 is small bumps and 1.0 is large bumps.</li>
  138. * </ul>
  139. * <li>NormalMap</li>
  140. * <ul>
  141. * <li><code>image</code>: path to image.</li>
  142. * <li><code>channels</code>: Three character string containing any combination of r, g, b, and a for selecting the desired image channels. </li>
  143. * <li><code>repeat</code>: Object with x and y values specifying the number of times to repeat the image.</li>
  144. * <li><code>strength</code>: Bump strength value between 0.0 and 1.0 where 0.0 is small bumps and 1.0 is large bumps.</li>
  145. * </ul>
  146. * <li>Grid</li>
  147. * <ul>
  148. * <li><code>color</code>: rgba color object for the whole material.</li>
  149. * <li><code>cellAlpha</code>: Alpha value for the cells between grid lines. This will be combined with color.alpha.</li>
  150. * <li><code>lineCount</code>: Object with x and y values specifying the number of columns and rows respectively.</li>
  151. * <li><code>lineThickness</code>: Object with x and y values specifying the thickness of grid lines (in pixels where available).</li>
  152. * <li><code>lineOffset</code>: Object with x and y values specifying the offset of grid lines (range is 0 to 1).</li>
  153. * </ul>
  154. * <li>Stripe</li>
  155. * <ul>
  156. * <li><code>horizontal</code>: Boolean that determines if the stripes are horizontal or vertical.</li>
  157. * <li><code>evenColor</code>: rgba color object for the stripe's first color.</li>
  158. * <li><code>oddColor</code>: rgba color object for the stripe's second color.</li>
  159. * <li><code>offset</code>: Number that controls at which point into the pattern to begin drawing; with 0.0 being the beginning of the even color, 1.0 the beginning of the odd color, 2.0 being the even color again, and any multiple or fractional values being in between.</li>
  160. * <li><code>repeat</code>: Number that controls the total number of stripes, half light and half dark.</li>
  161. * </ul>
  162. * <li>Checkerboard</li>
  163. * <ul>
  164. * <li><code>lightColor</code>: rgba color object for the checkerboard's light alternating color.</li>
  165. * <li><code>darkColor</code>: rgba color object for the checkerboard's dark alternating color.</li>
  166. * <li><code>repeat</code>: Object with x and y values specifying the number of columns and rows respectively.</li>
  167. * </ul>
  168. * <li>Dot</li>
  169. * <ul>
  170. * <li><code>lightColor</code>: rgba color object for the dot color.</li>
  171. * <li><code>darkColor</code>: rgba color object for the background color.</li>
  172. * <li><code>repeat</code>: Object with x and y values specifying the number of columns and rows of dots respectively.</li>
  173. * </ul>
  174. * <li>Water</li>
  175. * <ul>
  176. * <li><code>baseWaterColor</code>: rgba color object base color of the water.</li>
  177. * <li><code>blendColor</code>: rgba color object used when blending from water to non-water areas.</li>
  178. * <li><code>specularMap</code>: Single channel texture used to indicate areas of water.</li>
  179. * <li><code>normalMap</code>: Normal map for water normal perturbation.</li>
  180. * <li><code>frequency</code>: Number that controls the number of waves.</li>
  181. * <li><code>normalMap</code>: Normal map for water normal perturbation.</li>
  182. * <li><code>animationSpeed</code>: Number that controls the animations speed of the water.</li>
  183. * <li><code>amplitude</code>: Number that controls the amplitude of water waves.</li>
  184. * <li><code>specularIntensity</code>: Number that controls the intensity of specular reflections.</li>
  185. * </ul>
  186. * <li>RimLighting</li>
  187. * <ul>
  188. * <li><code>color</code>: diffuse color and alpha.</li>
  189. * <li><code>rimColor</code>: diffuse color and alpha of the rim.</li>
  190. * <li><code>width</code>: Number that determines the rim's width.</li>
  191. * </ul>
  192. * <li>Fade</li>
  193. * <ul>
  194. * <li><code>fadeInColor</code>: diffuse color and alpha at <code>time</code></li>
  195. * <li><code>fadeOutColor</code>: diffuse color and alpha at <code>maximumDistance<code> from <code>time</code></li>
  196. * <li><code>maximumDistance</code>: Number between 0.0 and 1.0 where the <code>fadeInColor</code> becomes the <code>fadeOutColor</code>. A value of 0.0 gives the entire material a color of <code>fadeOutColor</code> and a value of 1.0 gives the the entire material a color of <code>fadeInColor</code></li>
  197. * <li><code>repeat</code>: true if the fade should wrap around the texture coodinates.</li>
  198. * <li><code>fadeDirection</code>: Object with x and y values specifying if the fade should be in the x and y directions.</li>
  199. * <li><code>time</code>: Object with x and y values between 0.0 and 1.0 of the <code>fadeInColor</code> position</li>
  200. * </ul>
  201. * <li>PolylineArrow</li>
  202. * <ul>
  203. * <li><code>color</code>: diffuse color and alpha.</li>
  204. * </ul>
  205. * <li>PolylineGlow</li>
  206. * <ul>
  207. * <li><code>color</code>: color and maximum alpha for the glow on the line.</li>
  208. * <li><code>glowPower</code>: strength of the glow, as a percentage of the total line width (less than 1.0).</li>
  209. * </ul>
  210. * <li>PolylineOutline</li>
  211. * <ul>
  212. * <li><code>color</code>: diffuse color and alpha for the interior of the line.</li>
  213. * <li><code>outlineColor</code>: diffuse color and alpha for the outline.</li>
  214. * <li><code>outlineWidth</code>: width of the outline in pixels.</li>
  215. * </ul>
  216. * </ul>
  217. * </div>
  218. *
  219. * @alias Material
  220. *
  221. * @param {Object} [options] Object with the following properties:
  222. * @param {Boolean} [options.strict=false] Throws errors for issues that would normally be ignored, including unused uniforms or materials.
  223. * @param {Boolean|Function} [options.translucent=true] When <code>true</code> or a function that returns <code>true</code>, the geometry
  224. * with this material is expected to appear translucent.
  225. * @param {Object} options.fabric The fabric JSON used to generate the material.
  226. *
  227. * @constructor
  228. *
  229. * @exception {DeveloperError} fabric: uniform has invalid type.
  230. * @exception {DeveloperError} fabric: uniforms and materials cannot share the same property.
  231. * @exception {DeveloperError} fabric: cannot have source and components in the same section.
  232. * @exception {DeveloperError} fabric: property name is not valid. It should be 'type', 'materials', 'uniforms', 'components', or 'source'.
  233. * @exception {DeveloperError} fabric: property name is not valid. It should be 'diffuse', 'specular', 'shininess', 'normal', 'emission', or 'alpha'.
  234. * @exception {DeveloperError} strict: shader source does not use string.
  235. * @exception {DeveloperError} strict: shader source does not use uniform.
  236. * @exception {DeveloperError} strict: shader source does not use material.
  237. *
  238. * @see {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric wiki page} for a more detailed options of Fabric.
  239. *
  240. * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Materials.html|Cesium Sandcastle Materials Demo}
  241. *
  242. * @example
  243. * // Create a color material with fromType:
  244. * polygon.material = Cesium.Material.fromType('Color');
  245. * polygon.material.uniforms.color = new Cesium.Color(1.0, 1.0, 0.0, 1.0);
  246. *
  247. * // Create the default material:
  248. * polygon.material = new Cesium.Material();
  249. *
  250. * // Create a color material with full Fabric notation:
  251. * polygon.material = new Cesium.Material({
  252. * fabric : {
  253. * type : 'Color',
  254. * uniforms : {
  255. * color : new Cesium.Color(1.0, 1.0, 0.0, 1.0)
  256. * }
  257. * }
  258. * });
  259. */
  260. var Material = function(options) {
  261. /**
  262. * The material type. Can be an existing type or a new type. If no type is specified in fabric, type is a GUID.
  263. * @type {String}
  264. * @default undefined
  265. */
  266. this.type = undefined;
  267. /**
  268. * The glsl shader source for this material.
  269. * @type {String}
  270. * @default undefined
  271. */
  272. this.shaderSource = undefined;
  273. /**
  274. * Maps sub-material names to Material objects.
  275. * @type {Object}
  276. * @default undefined
  277. */
  278. this.materials = undefined;
  279. /**
  280. * Maps uniform names to their values.
  281. * @type {Object}
  282. * @default undefined
  283. */
  284. this.uniforms = undefined;
  285. this._uniforms = undefined;
  286. /**
  287. * When <code>true</code> or a function that returns <code>true</code>,
  288. * the geometry is expected to appear translucent.
  289. * @type {Boolean|Function}
  290. * @default undefined
  291. */
  292. this.translucent = undefined;
  293. this._strict = undefined;
  294. this._template = undefined;
  295. this._count = undefined;
  296. this._texturePaths = {};
  297. this._loadedImages = [];
  298. this._loadedCubeMaps = [];
  299. this._textures = {};
  300. this._updateFunctions = [];
  301. initializeMaterial(options, this);
  302. defineProperties(this, {
  303. type : {
  304. value : this.type,
  305. writable : false
  306. }
  307. });
  308. if (!defined(Material._uniformList[this.type])) {
  309. Material._uniformList[this.type] = Object.keys(this._uniforms);
  310. }
  311. };
  312. // Cached list of combined uniform names indexed by type.
  313. // Used to get the list of uniforms in the same order.
  314. Material._uniformList = {};
  315. /**
  316. * Creates a new material using an existing material type.
  317. * <br /><br />
  318. * Shorthand for: new Material({fabric : {type : type}});
  319. *
  320. * @param {String} type The base material type.
  321. * @param {Object} [uniforms] Overrides for the default uniforms.
  322. * @returns {Material} New material object.
  323. *
  324. * @exception {DeveloperError} material with that type does not exist.
  325. *
  326. * @example
  327. * var material = Cesium.Material.fromType('Color', {
  328. * color : new Cesium.Color(1.0, 0.0, 0.0, 1.0)
  329. * });
  330. */
  331. Material.fromType = function(type, uniforms) {
  332. //>>includeStart('debug', pragmas.debug);
  333. if (!defined(Material._materialCache.getMaterial(type))) {
  334. throw new DeveloperError('material with type \'' + type + '\' does not exist.');
  335. }
  336. //>>includeEnd('debug');
  337. var material = new Material({
  338. fabric : {
  339. type : type
  340. }
  341. });
  342. if (defined(uniforms)) {
  343. for (var name in uniforms) {
  344. if (uniforms.hasOwnProperty(name)) {
  345. material.uniforms[name] = uniforms[name];
  346. }
  347. }
  348. }
  349. return material;
  350. };
  351. /**
  352. * Gets whether or not this material is translucent.
  353. * @returns <code>true</code> if this material is translucent, <code>false</code> otherwise.
  354. */
  355. Material.prototype.isTranslucent = function() {
  356. if (defined(this.translucent)) {
  357. if (typeof this.translucent === 'function') {
  358. return this.translucent();
  359. }
  360. return this.translucent;
  361. }
  362. var translucent = true;
  363. var funcs = this._translucentFunctions;
  364. var length = funcs.length;
  365. for (var i = 0; i < length; ++i) {
  366. var func = funcs[i];
  367. if (typeof func === 'function') {
  368. translucent = translucent && func();
  369. } else {
  370. translucent = translucent && func;
  371. }
  372. if (!translucent) {
  373. break;
  374. }
  375. }
  376. return translucent;
  377. };
  378. /**
  379. * @private
  380. */
  381. Material.prototype.update = function(context) {
  382. var i;
  383. var uniformId;
  384. var loadedImages = this._loadedImages;
  385. var length = loadedImages.length;
  386. for (i = 0; i < length; ++i) {
  387. var loadedImage = loadedImages[i];
  388. uniformId = loadedImage.id;
  389. var image = loadedImage.image;
  390. var texture = Material._textureCache.getTexture(this._texturePaths[uniformId]);
  391. if (!defined(texture)) {
  392. texture = context.createTexture2D({
  393. source : image
  394. });
  395. Material._textureCache.addTexture(this._texturePaths[uniformId], texture);
  396. }
  397. this._textures[uniformId] = texture;
  398. var uniformDimensionsName = uniformId + 'Dimensions';
  399. if (this.uniforms.hasOwnProperty(uniformDimensionsName)) {
  400. var uniformDimensions = this.uniforms[uniformDimensionsName];
  401. uniformDimensions.x = texture._width;
  402. uniformDimensions.y = texture._height;
  403. }
  404. }
  405. loadedImages.length = 0;
  406. var loadedCubeMaps = this._loadedCubeMaps;
  407. length = loadedCubeMaps.length;
  408. for (i = 0; i < length; ++i) {
  409. var loadedCubeMap = loadedCubeMaps[i];
  410. uniformId = loadedCubeMap.id;
  411. var images = loadedCubeMap.images;
  412. var cubeMap = Material._textureCache.getTexture(this._texturePaths[uniformId]);
  413. if (!defined(cubeMap)) {
  414. cubeMap = context.createCubeMap({
  415. source : {
  416. positiveX : images[0],
  417. negativeX : images[1],
  418. positiveY : images[2],
  419. negativeY : images[3],
  420. positiveZ : images[4],
  421. negativeZ : images[5]
  422. }
  423. });
  424. Material._textureCache.addTexture(this._texturePaths[uniformId], cubeMap);
  425. }
  426. this._textures[uniformId] = cubeMap;
  427. }
  428. loadedCubeMaps.length = 0;
  429. var updateFunctions = this._updateFunctions;
  430. length = updateFunctions.length;
  431. for (i = 0; i < length; ++i) {
  432. updateFunctions[i](this, context);
  433. }
  434. var subMaterials = this.materials;
  435. for (var name in subMaterials) {
  436. if (subMaterials.hasOwnProperty(name)) {
  437. subMaterials[name].update(context);
  438. }
  439. }
  440. };
  441. /**
  442. * Returns true if this object was destroyed; otherwise, false.
  443. * <br /><br />
  444. * If this object was destroyed, it should not be used; calling any function other than
  445. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  446. *
  447. * @returns {Boolean} True if this object was destroyed; otherwise, false.
  448. *
  449. * @see Material#destroy
  450. */
  451. Material.prototype.isDestroyed = function() {
  452. return false;
  453. };
  454. /**
  455. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  456. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  457. * <br /><br />
  458. * Once an object is destroyed, it should not be used; calling any function other than
  459. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  460. * assign the return value (<code>undefined</code>) to the object as done in the example.
  461. *
  462. * @returns {undefined}
  463. *
  464. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  465. *
  466. * @see Material#isDestroyed
  467. *
  468. * @example
  469. * material = material && material.destroy();
  470. */
  471. Material.prototype.destroy = function() {
  472. var materials = this.materials;
  473. var uniforms = this.uniforms;
  474. for ( var uniformId in uniforms) {
  475. if (uniforms.hasOwnProperty(uniformId)) {
  476. var path = this._texturePaths[uniformId];
  477. Material._textureCache.releaseTexture(path);
  478. }
  479. }
  480. for ( var material in materials) {
  481. if (materials.hasOwnProperty(material)) {
  482. materials[material].destroy();
  483. }
  484. }
  485. return destroyObject(this);
  486. };
  487. function initializeMaterial(options, result) {
  488. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  489. result._strict = defaultValue(options.strict, false);
  490. result._count = defaultValue(options.count, 0);
  491. result._template = clone(defaultValue(options.fabric, defaultValue.EMPTY_OBJECT));
  492. result._template.uniforms = clone(defaultValue(result._template.uniforms, defaultValue.EMPTY_OBJECT));
  493. result._template.materials = clone(defaultValue(result._template.materials, defaultValue.EMPTY_OBJECT));
  494. result.type = defined(result._template.type) ? result._template.type : createGuid();
  495. result.shaderSource = '';
  496. result.materials = {};
  497. result.uniforms = {};
  498. result._uniforms = {};
  499. result._translucentFunctions = [];
  500. var translucent;
  501. // If the cache contains this material type, build the material template off of the stored template.
  502. var cachedMaterial = Material._materialCache.getMaterial(result.type);
  503. if (defined(cachedMaterial)) {
  504. var template = clone(cachedMaterial.fabric, true);
  505. result._template = combine(result._template, template, true);
  506. translucent = cachedMaterial.translucent;
  507. }
  508. // Make sure the template has no obvious errors. More error checking happens later.
  509. checkForTemplateErrors(result);
  510. // If the material has a new type, add it to the cache.
  511. if (!defined(cachedMaterial)) {
  512. Material._materialCache.addMaterial(result.type, result);
  513. }
  514. createMethodDefinition(result);
  515. createUniforms(result);
  516. createSubMaterials(result);
  517. var defaultTranslucent = result._translucentFunctions.length === 0 ? true : undefined;
  518. translucent = defaultValue(translucent, defaultTranslucent);
  519. translucent = defaultValue(options.translucent, translucent);
  520. if (defined(translucent)) {
  521. if (typeof translucent === 'function') {
  522. var wrappedTranslucent = function() {
  523. return translucent(result);
  524. };
  525. result._translucentFunctions.push(wrappedTranslucent);
  526. } else {
  527. result._translucentFunctions.push(translucent);
  528. }
  529. }
  530. }
  531. function checkForValidProperties(object, properties, result, throwNotFound) {
  532. if (defined(object)) {
  533. for ( var property in object) {
  534. if (object.hasOwnProperty(property)) {
  535. var hasProperty = properties.indexOf(property) !== -1;
  536. if ((throwNotFound && !hasProperty) || (!throwNotFound && hasProperty)) {
  537. result(property, properties);
  538. }
  539. }
  540. }
  541. }
  542. }
  543. function invalidNameError(property, properties) {
  544. var errorString = 'fabric: property name \'' + property + '\' is not valid. It should be ';
  545. for ( var i = 0; i < properties.length; i++) {
  546. var propertyName = '\'' + properties[i] + '\'';
  547. errorString += (i === properties.length - 1) ? ('or ' + propertyName + '.') : (propertyName + ', ');
  548. }
  549. throw new DeveloperError(errorString);
  550. }
  551. function duplicateNameError(property, properties) {
  552. var errorString = 'fabric: uniforms and materials cannot share the same property \'' + property + '\'';
  553. throw new DeveloperError(errorString);
  554. }
  555. var templateProperties = ['type', 'materials', 'uniforms', 'components', 'source'];
  556. var componentProperties = ['diffuse', 'specular', 'shininess', 'normal', 'emission', 'alpha'];
  557. function checkForTemplateErrors(material) {
  558. var template = material._template;
  559. var uniforms = template.uniforms;
  560. var materials = template.materials;
  561. var components = template.components;
  562. // Make sure source and components do not exist in the same template.
  563. if (defined(components) && defined(template.source)) {
  564. throw new DeveloperError('fabric: cannot have source and components in the same template.');
  565. }
  566. // Make sure all template and components properties are valid.
  567. checkForValidProperties(template, templateProperties, invalidNameError, true);
  568. checkForValidProperties(components, componentProperties, invalidNameError, true);
  569. // Make sure uniforms and materials do not share any of the same names.
  570. var materialNames = [];
  571. for ( var property in materials) {
  572. if (materials.hasOwnProperty(property)) {
  573. materialNames.push(property);
  574. }
  575. }
  576. checkForValidProperties(uniforms, materialNames, duplicateNameError, false);
  577. }
  578. // Create the czm_getMaterial method body using source or components.
  579. function createMethodDefinition(material) {
  580. var components = material._template.components;
  581. var source = material._template.source;
  582. if (defined(source)) {
  583. material.shaderSource += source + '\n';
  584. } else {
  585. material.shaderSource += 'czm_material czm_getMaterial(czm_materialInput materialInput)\n{\n';
  586. material.shaderSource += 'czm_material material = czm_getDefaultMaterial(materialInput);\n';
  587. if (defined(components)) {
  588. for ( var component in components) {
  589. if (components.hasOwnProperty(component)) {
  590. material.shaderSource += 'material.' + component + ' = ' + components[component] + ';\n';
  591. }
  592. }
  593. }
  594. material.shaderSource += 'return material;\n}\n';
  595. }
  596. }
  597. var matrixMap = {
  598. 'mat2' : Matrix2,
  599. 'mat3' : Matrix3,
  600. 'mat4' : Matrix4
  601. };
  602. function createTexture2DUpdateFunction(uniformId) {
  603. return function(material, context) {
  604. var uniforms = material.uniforms;
  605. var uniformValue = uniforms[uniformId];
  606. var texture = material._textures[uniformId];
  607. var uniformDimensionsName;
  608. var uniformDimensions;
  609. if (uniformValue instanceof Texture && uniformValue !== texture) {
  610. Material._textureCache.releaseTexture(material._texturePaths[uniformId]);
  611. material._texturePaths[uniformId] = undefined;
  612. material._textures[uniformId] = uniformValue;
  613. uniformDimensionsName = uniformId + 'Dimensions';
  614. if (uniforms.hasOwnProperty(uniformDimensionsName)) {
  615. uniformDimensions = uniforms[uniformDimensionsName];
  616. uniformDimensions.x = uniformValue._width;
  617. uniformDimensions.y = uniformValue._height;
  618. }
  619. return;
  620. }
  621. if (!defined(texture)) {
  622. material._texturePaths[uniformId] = undefined;
  623. texture = material._textures[uniformId] = context.defaultTexture;
  624. uniformDimensionsName = uniformId + 'Dimensions';
  625. if (uniforms.hasOwnProperty(uniformDimensionsName)) {
  626. uniformDimensions = uniforms[uniformDimensionsName];
  627. uniformDimensions.x = texture._width;
  628. uniformDimensions.y = texture._height;
  629. }
  630. }
  631. if (uniformValue === Material.DefaultImageId) {
  632. return;
  633. }
  634. if (uniformValue !== material._texturePaths[uniformId]) {
  635. var newTexture = Material._textureCache.getTexture(uniformValue);
  636. if (defined(newTexture)) {
  637. Material._textureCache.releaseTexture(material._texturePaths[uniformId]);
  638. material._textures[uniformId] = newTexture;
  639. } else {
  640. when(loadImage(uniformValue), function(image) {
  641. material._loadedImages.push({
  642. id : uniformId,
  643. image : image
  644. });
  645. });
  646. }
  647. material._texturePaths[uniformId] = uniformValue;
  648. }
  649. };
  650. }
  651. function createCubeMapUpdateFunction(uniformId) {
  652. return function(material, context) {
  653. var uniformValue = material.uniforms[uniformId];
  654. if (uniformValue instanceof CubeMap) {
  655. Material._textureCache.releaseTexture(material._texturePaths[uniformId]);
  656. material._texturePaths[uniformId] = undefined;
  657. material._textures[uniformId] = uniformValue;
  658. return;
  659. }
  660. if (!defined(material._textures[uniformId])) {
  661. material._texturePaths[uniformId] = undefined;
  662. material._textures[uniformId] = context.defaultCubeMap;
  663. }
  664. if (uniformValue === Material.DefaultCubeMapId) {
  665. return;
  666. }
  667. var path =
  668. uniformValue.positiveX + uniformValue.negativeX +
  669. uniformValue.positiveY + uniformValue.negativeY +
  670. uniformValue.positiveZ + uniformValue.negativeZ;
  671. if (path !== material._texturePaths[uniformId]) {
  672. var newTexture = Material._textureCache.getTexture(path);
  673. if (defined(newTexture)) {
  674. Material._textureCache.releaseTexture(material._texturePaths[uniformId]);
  675. material._textures[uniformId] = newTexture;
  676. } else {
  677. var promises = [
  678. loadImage(uniformValue.positiveX),
  679. loadImage(uniformValue.negativeX),
  680. loadImage(uniformValue.positiveY),
  681. loadImage(uniformValue.negativeY),
  682. loadImage(uniformValue.positiveZ),
  683. loadImage(uniformValue.negativeZ)
  684. ];
  685. when.all(promises).then(function(images) {
  686. material._loadedCubeMaps.push({
  687. id : uniformId,
  688. images : images
  689. });
  690. });
  691. }
  692. material._texturePaths[uniformId] = path;
  693. }
  694. };
  695. }
  696. function createUniforms(material) {
  697. var uniforms = material._template.uniforms;
  698. for ( var uniformId in uniforms) {
  699. if (uniforms.hasOwnProperty(uniformId)) {
  700. createUniform(material, uniformId);
  701. }
  702. }
  703. }
  704. // Writes uniform declarations to the shader file and connects uniform values with
  705. // corresponding material properties through the returnUniforms function.
  706. function createUniform(material, uniformId) {
  707. var strict = material._strict;
  708. var materialUniforms = material._template.uniforms;
  709. var uniformValue = materialUniforms[uniformId];
  710. var uniformType = getUniformType(uniformValue);
  711. if (!defined(uniformType)) {
  712. throw new DeveloperError('fabric: uniform \'' + uniformId + '\' has invalid type.');
  713. } else if (uniformType === 'channels') {
  714. if (replaceToken(material, uniformId, uniformValue, false) === 0 && strict) {
  715. throw new DeveloperError('strict: shader source does not use channels \'' + uniformId + '\'.');
  716. }
  717. } else {
  718. // Since webgl doesn't allow texture dimension queries in glsl, create a uniform to do it.
  719. // Check if the shader source actually uses texture dimensions before creating the uniform.
  720. if (uniformType === 'sampler2D') {
  721. var imageDimensionsUniformName = uniformId + 'Dimensions';
  722. if (getNumberOfTokens(material, imageDimensionsUniformName) > 0) {
  723. materialUniforms[imageDimensionsUniformName] = {
  724. type : 'ivec3',
  725. x : 1,
  726. y : 1
  727. };
  728. createUniform(material, imageDimensionsUniformName);
  729. }
  730. }
  731. // Add uniform declaration to source code.
  732. var uniformDeclarationRegex = new RegExp('uniform\\s+' + uniformType + '\\s+' + uniformId + '\\s*;');
  733. if (!uniformDeclarationRegex.test(material.shaderSource)) {
  734. var uniformDeclaration = 'uniform ' + uniformType + ' ' + uniformId + ';';
  735. material.shaderSource = uniformDeclaration + material.shaderSource;
  736. }
  737. var newUniformId = uniformId + '_' + material._count++;
  738. if (replaceToken(material, uniformId, newUniformId) === 1 && strict) {
  739. throw new DeveloperError('strict: shader source does not use uniform \'' + uniformId + '\'.');
  740. }
  741. // Set uniform value
  742. material.uniforms[uniformId] = uniformValue;
  743. if (uniformType === 'sampler2D') {
  744. material._uniforms[newUniformId] = function() {
  745. return material._textures[uniformId];
  746. };
  747. material._updateFunctions.push(createTexture2DUpdateFunction(uniformId));
  748. } else if (uniformType === 'samplerCube') {
  749. material._uniforms[newUniformId] = function() {
  750. return material._textures[uniformId];
  751. };
  752. material._updateFunctions.push(createCubeMapUpdateFunction(uniformId));
  753. } else if (uniformType.indexOf('mat') !== -1) {
  754. var scratchMatrix = new matrixMap[uniformType]();
  755. material._uniforms[newUniformId] = function() {
  756. return matrixMap[uniformType].fromColumnMajorArray(material.uniforms[uniformId], scratchMatrix);
  757. };
  758. } else {
  759. material._uniforms[newUniformId] = function() {
  760. return material.uniforms[uniformId];
  761. };
  762. }
  763. }
  764. }
  765. // Determines the uniform type based on the uniform in the template.
  766. function getUniformType(uniformValue) {
  767. var uniformType = uniformValue.type;
  768. if (!defined(uniformType)) {
  769. var type = typeof uniformValue;
  770. if (type === 'number') {
  771. uniformType = 'float';
  772. } else if (type === 'boolean') {
  773. uniformType = 'bool';
  774. } else if (type === 'string') {
  775. if (/^([rgba]){1,4}$/i.test(uniformValue)) {
  776. uniformType = 'channels';
  777. } else if (uniformValue === Material.DefaultCubeMapId) {
  778. uniformType = 'samplerCube';
  779. } else {
  780. uniformType = 'sampler2D';
  781. }
  782. } else if (type === 'object') {
  783. if (isArray(uniformValue)) {
  784. if (uniformValue.length === 4 || uniformValue.length === 9 || uniformValue.length === 16) {
  785. uniformType = 'mat' + Math.sqrt(uniformValue.length);
  786. }
  787. } else {
  788. var numAttributes = 0;
  789. for ( var attribute in uniformValue) {
  790. if (uniformValue.hasOwnProperty(attribute)) {
  791. numAttributes += 1;
  792. }
  793. }
  794. if (numAttributes >= 2 && numAttributes <= 4) {
  795. uniformType = 'vec' + numAttributes;
  796. } else if (numAttributes === 6) {
  797. uniformType = 'samplerCube';
  798. }
  799. }
  800. }
  801. }
  802. return uniformType;
  803. }
  804. // Create all sub-materials by combining source and uniforms together.
  805. function createSubMaterials(material) {
  806. var strict = material._strict;
  807. var subMaterialTemplates = material._template.materials;
  808. for ( var subMaterialId in subMaterialTemplates) {
  809. if (subMaterialTemplates.hasOwnProperty(subMaterialId)) {
  810. // Construct the sub-material.
  811. var subMaterial = new Material({
  812. strict : strict,
  813. fabric : subMaterialTemplates[subMaterialId],
  814. count : material._count
  815. });
  816. material._count = subMaterial._count;
  817. material._uniforms = combine(material._uniforms, subMaterial._uniforms, true);
  818. material.materials[subMaterialId] = subMaterial;
  819. material._translucentFunctions = material._translucentFunctions.concat(subMaterial._translucentFunctions);
  820. // Make the material's czm_getMaterial unique by appending the sub-material type.
  821. var originalMethodName = 'czm_getMaterial';
  822. var newMethodName = originalMethodName + '_' + material._count++;
  823. replaceToken(subMaterial, originalMethodName, newMethodName);
  824. material.shaderSource = subMaterial.shaderSource + material.shaderSource;
  825. // Replace each material id with an czm_getMaterial method call.
  826. var materialMethodCall = newMethodName + '(materialInput)';
  827. if (replaceToken(material, subMaterialId, materialMethodCall) === 0 && strict) {
  828. throw new DeveloperError('strict: shader source does not use material \'' + subMaterialId + '\'.');
  829. }
  830. }
  831. }
  832. }
  833. // Used for searching or replacing a token in a material's shader source with something else.
  834. // If excludePeriod is true, do not accept tokens that are preceded by periods.
  835. // http://stackoverflow.com/questions/641407/javascript-negative-lookbehind-equivalent
  836. function replaceToken(material, token, newToken, excludePeriod) {
  837. excludePeriod = defaultValue(excludePeriod, true);
  838. var count = 0;
  839. var suffixChars = '([\\w])?';
  840. var prefixChars = '([\\w' + (excludePeriod ? '.' : '') + '])?';
  841. var regExp = new RegExp(prefixChars + token + suffixChars, 'g');
  842. material.shaderSource = material.shaderSource.replace(regExp, function($0, $1, $2) {
  843. if ($1 || $2) {
  844. return $0;
  845. }
  846. count += 1;
  847. return newToken;
  848. });
  849. return count;
  850. }
  851. function getNumberOfTokens(material, token, excludePeriod) {
  852. return replaceToken(material, token, token, excludePeriod);
  853. }
  854. Material._textureCache = {
  855. _textures : {},
  856. addTexture : function(path, texture) {
  857. this._textures[path] = {
  858. texture : texture,
  859. count : 1
  860. };
  861. },
  862. getTexture : function(path) {
  863. var entry = this._textures[path];
  864. if (defined(entry)) {
  865. entry.count++;
  866. return entry.texture;
  867. }
  868. return undefined;
  869. },
  870. releaseTexture : function(path) {
  871. var entry = this._textures[path];
  872. if (defined(entry) && --entry.count === 0) {
  873. entry.texture = entry.texture && entry.texture.destroy();
  874. this._textures[path] = undefined;
  875. }
  876. }
  877. };
  878. Material._materialCache = {
  879. _materials : {},
  880. addMaterial : function(type, materialTemplate) {
  881. this._materials[type] = materialTemplate;
  882. },
  883. getMaterial : function(type) {
  884. return this._materials[type];
  885. }
  886. };
  887. /**
  888. * Gets or sets the default texture uniform value.
  889. * @type {String}
  890. */
  891. Material.DefaultImageId = 'czm_defaultImage';
  892. /**
  893. * Gets or sets the default cube map texture uniform value.
  894. * @type {String}
  895. */
  896. Material.DefaultCubeMapId = 'czm_defaultCubeMap';
  897. /**
  898. * Gets the name of the color material.
  899. * @type {String}
  900. * @readonly
  901. */
  902. Material.ColorType = 'Color';
  903. Material._materialCache.addMaterial(Material.ColorType, {
  904. fabric : {
  905. type : Material.ColorType,
  906. uniforms : {
  907. color : new Color(1.0, 0.0, 0.0, 0.5)
  908. },
  909. components : {
  910. diffuse : 'color.rgb',
  911. alpha : 'color.a'
  912. }
  913. },
  914. translucent : function(material) {
  915. return material.uniforms.color.alpha < 1.0;
  916. }
  917. });
  918. /**
  919. * Gets the name of the image material.
  920. * @type {String}
  921. * @readonly
  922. */
  923. Material.ImageType = 'Image';
  924. Material._materialCache.addMaterial(Material.ImageType, {
  925. fabric : {
  926. type : Material.ImageType,
  927. uniforms : {
  928. image : Material.DefaultImageId,
  929. repeat : new Cartesian2(1.0, 1.0)
  930. },
  931. components : {
  932. diffuse : 'texture2D(image, fract(repeat * materialInput.st)).rgb',
  933. alpha : 'texture2D(image, fract(repeat * materialInput.st)).a'
  934. }
  935. },
  936. translucent : true
  937. });
  938. /**
  939. * Gets the name of the diffuce map material.
  940. * @type {String}
  941. * @readonly
  942. */
  943. Material.DiffuseMapType = 'DiffuseMap';
  944. Material._materialCache.addMaterial(Material.DiffuseMapType, {
  945. fabric : {
  946. type : Material.DiffuseMapType,
  947. uniforms : {
  948. image : Material.DefaultImageId,
  949. channels : 'rgb',
  950. repeat : new Cartesian2(1.0, 1.0)
  951. },
  952. components : {
  953. diffuse : 'texture2D(image, fract(repeat * materialInput.st)).channels'
  954. }
  955. },
  956. translucent : false
  957. });
  958. /**
  959. * Gets the name of the alpha map material.
  960. * @type {String}
  961. * @readonly
  962. */
  963. Material.AlphaMapType = 'AlphaMap';
  964. Material._materialCache.addMaterial(Material.AlphaMapType, {
  965. fabric : {
  966. type : Material.AlphaMapType,
  967. uniforms : {
  968. image : Material.DefaultImageId,
  969. channel : 'a',
  970. repeat : new Cartesian2(1.0, 1.0)
  971. },
  972. components : {
  973. alpha : 'texture2D(image, fract(repeat * materialInput.st)).channel'
  974. }
  975. },
  976. translucent : true
  977. });
  978. /**
  979. * Gets the name of the specular map material.
  980. * @type {String}
  981. * @readonly
  982. */
  983. Material.SpecularMapType = 'SpecularMap';
  984. Material._materialCache.addMaterial(Material.SpecularMapType, {
  985. fabric : {
  986. type : Material.SpecularMapType,
  987. uniforms : {
  988. image : Material.DefaultImageId,
  989. channel : 'r',
  990. repeat : new Cartesian2(1.0, 1.0)
  991. },
  992. components : {
  993. specular : 'texture2D(image, fract(repeat * materialInput.st)).channel'
  994. }
  995. },
  996. translucent : false
  997. });
  998. /**
  999. * Gets the name of the emmision map material.
  1000. * @type {String}
  1001. * @readonly
  1002. */
  1003. Material.EmissionMapType = 'EmissionMap';
  1004. Material._materialCache.addMaterial(Material.EmissionMapType, {
  1005. fabric : {
  1006. type : Material.EmissionMapType,
  1007. uniforms : {
  1008. image : Material.DefaultImageId,
  1009. channels : 'rgb',
  1010. repeat : new Cartesian2(1.0, 1.0)
  1011. },
  1012. components : {
  1013. emission : 'texture2D(image, fract(repeat * materialInput.st)).channels'
  1014. }
  1015. },
  1016. translucent : false
  1017. });
  1018. /**
  1019. * Gets the name of the bump map material.
  1020. * @type {String}
  1021. * @readonly
  1022. */
  1023. Material.BumpMapType = 'BumpMap';
  1024. Material._materialCache.addMaterial(Material.BumpMapType, {
  1025. fabric : {
  1026. type : Material.BumpMapType,
  1027. uniforms : {
  1028. image : Material.DefaultImageId,
  1029. channel : 'r',
  1030. strength : 0.8,
  1031. repeat : new Cartesian2(1.0, 1.0)
  1032. },
  1033. source : BumpMapMaterial
  1034. },
  1035. translucent : false
  1036. });
  1037. /**
  1038. * Gets the name of the normal map material.
  1039. * @type {String}
  1040. * @readonly
  1041. */
  1042. Material.NormalMapType = 'NormalMap';
  1043. Material._materialCache.addMaterial(Material.NormalMapType, {
  1044. fabric : {
  1045. type : Material.NormalMapType,
  1046. uniforms : {
  1047. image : Material.DefaultImageId,
  1048. channels : 'rgb',
  1049. strength : 0.8,
  1050. repeat : new Cartesian2(1.0, 1.0)
  1051. },
  1052. source : NormalMapMaterial
  1053. },
  1054. translucent : false
  1055. });
  1056. /**
  1057. * Gets the name of the grid material.
  1058. * @type {String}
  1059. * @readonly
  1060. */
  1061. Material.GridType = 'Grid';
  1062. Material._materialCache.addMaterial(Material.GridType, {
  1063. fabric : {
  1064. type : Material.GridType,
  1065. uniforms : {
  1066. color : new Color(0.0, 1.0, 0.0, 1.0),
  1067. cellAlpha : 0.1,
  1068. lineCount : new Cartesian2(8.0, 8.0),
  1069. lineThickness : new Cartesian2(1.0, 1.0),
  1070. lineOffset : new Cartesian2(0.0, 0.0)
  1071. },
  1072. source : GridMaterial
  1073. },
  1074. translucent : function(material) {
  1075. var uniforms = material.uniforms;
  1076. return (uniforms.color.alpha < 1.0) || (uniforms.cellAlpha < 1.0);
  1077. }
  1078. });
  1079. /**
  1080. * Gets the name of the stripe material.
  1081. * @type {String}
  1082. * @readonly
  1083. */
  1084. Material.StripeType = 'Stripe';
  1085. Material._materialCache.addMaterial(Material.StripeType, {
  1086. fabric : {
  1087. type : Material.StripeType,
  1088. uniforms : {
  1089. horizontal : true,
  1090. evenColor : new Color(1.0, 1.0, 1.0, 0.5),
  1091. oddColor : new Color(0.0, 0.0, 1.0, 0.5),
  1092. offset : 0.0,
  1093. repeat : 5.0
  1094. },
  1095. source : StripeMaterial
  1096. },
  1097. translucent : function(material) {
  1098. var uniforms = material.uniforms;
  1099. return (uniforms.evenColor.alpha < 1.0) || (uniforms.oddColor.alpha < 0.0);
  1100. }
  1101. });
  1102. /**
  1103. * Gets the name of the checkerboard material.
  1104. * @type {String}
  1105. * @readonly
  1106. */
  1107. Material.CheckerboardType = 'Checkerboard';
  1108. Material._materialCache.addMaterial(Material.CheckerboardType, {
  1109. fabric : {
  1110. type : Material.CheckerboardType,
  1111. uniforms : {
  1112. lightColor : new Color(1.0, 1.0, 1.0, 0.5),
  1113. darkColor : new Color(0.0, 0.0, 0.0, 0.5),
  1114. repeat : new Cartesian2(5.0, 5.0)
  1115. },
  1116. source : CheckerboardMaterial
  1117. },
  1118. translucent : function(material) {
  1119. var uniforms = material.uniforms;
  1120. return (uniforms.lightColor.alpha < 1.0) || (uniforms.darkColor.alpha < 0.0);
  1121. }
  1122. });
  1123. /**
  1124. * Gets the name of the dot material.
  1125. * @type {String}
  1126. * @readonly
  1127. */
  1128. Material.DotType = 'Dot';
  1129. Material._materialCache.addMaterial(Material.DotType, {
  1130. fabric : {
  1131. type : Material.DotType,
  1132. uniforms : {
  1133. lightColor : new Color(1.0, 1.0, 0.0, 0.75),
  1134. darkColor : new Color(0.0, 1.0, 1.0, 0.75),
  1135. repeat : new Cartesian2(5.0, 5.0)
  1136. },
  1137. source : DotMaterial
  1138. },
  1139. translucent : function(material) {
  1140. var uniforms = material.uniforms;
  1141. return (uniforms.lightColor.alpha < 1.0) || (uniforms.darkColor.alpha < 0.0);
  1142. }
  1143. });
  1144. /**
  1145. * Gets the name of the water material.
  1146. * @type {String}
  1147. * @readonly
  1148. */
  1149. Material.WaterType = 'Water';
  1150. Material._materialCache.addMaterial(Material.WaterType, {
  1151. fabric : {
  1152. type : Material.WaterType,
  1153. uniforms : {
  1154. baseWaterColor : new Color(0.2, 0.3, 0.6, 1.0),
  1155. blendColor : new Color(0.0, 1.0, 0.699, 1.0),
  1156. specularMap : Material.DefaultImageId,
  1157. normalMap : Material.DefaultImageId,
  1158. frequency : 10.0,
  1159. animationSpeed : 0.01,
  1160. amplitude : 1.0,
  1161. specularIntensity : 0.5,
  1162. fadeFactor : 1.0
  1163. },
  1164. source : WaterMaterial
  1165. },
  1166. translucent : function(material) {
  1167. var uniforms = material.uniforms;
  1168. return (uniforms.baseWaterColor.alpha < 1.0) || (uniforms.blendColor.alpha < 0.0);
  1169. }
  1170. });
  1171. /**
  1172. * Gets the name of the rim lighting material.
  1173. * @type {String}
  1174. * @readonly
  1175. */
  1176. Material.RimLightingType = 'RimLighting';
  1177. Material._materialCache.addMaterial(Material.RimLightingType, {
  1178. fabric : {
  1179. type : Material.RimLightingType,
  1180. uniforms : {
  1181. color : new Color(1.0, 0.0, 0.0, 0.7),
  1182. rimColor : new Color(1.0, 1.0, 1.0, 0.4),
  1183. width : 0.3
  1184. },
  1185. source : RimLightingMaterial
  1186. },
  1187. translucent : function(material) {
  1188. var uniforms = material.uniforms;
  1189. return (uniforms.color.alpha < 1.0) || (uniforms.rimColor.alpha < 0.0);
  1190. }
  1191. });
  1192. /**
  1193. * Gets the name of the fade material.
  1194. * @type {String}
  1195. * @readonly
  1196. */
  1197. Material.FadeType = 'Fade';
  1198. Material._materialCache.addMaterial(Material.FadeType, {
  1199. fabric : {
  1200. type : Material.FadeType,
  1201. uniforms : {
  1202. fadeInColor : new Color(1.0, 0.0, 0.0, 1.0),
  1203. fadeOutColor : new Color(0.0, 0.0, 0.0, 0.0),
  1204. maximumDistance : 0.5,
  1205. repeat : true,
  1206. fadeDirection : {
  1207. x : true,
  1208. y : true
  1209. },
  1210. time : new Cartesian2(0.5, 0.5)
  1211. },
  1212. source : FadeMaterial
  1213. },
  1214. translucent : function(material) {
  1215. var uniforms = material.uniforms;
  1216. return (uniforms.fadeInColor.alpha < 1.0) || (uniforms.fadeOutColor.alpha < 0.0);
  1217. }
  1218. });
  1219. /**
  1220. * Gets the name of the polyline arrow material.
  1221. * @type {String}
  1222. * @readonly
  1223. */
  1224. Material.PolylineArrowType = 'PolylineArrow';
  1225. Material._materialCache.addMaterial(Material.PolylineArrowType, {
  1226. fabric : {
  1227. type : Material.PolylineArrowType,
  1228. uniforms : {
  1229. color : new Color(1.0, 1.0, 1.0, 1.0)
  1230. },
  1231. source : PolylineArrowMaterial
  1232. },
  1233. translucent : true
  1234. });
  1235. /**
  1236. * Gets the name of the polyline glow material.
  1237. * @type {String}
  1238. * @readonly
  1239. */
  1240. Material.PolylineGlowType = 'PolylineGlow';
  1241. Material._materialCache.addMaterial(Material.PolylineGlowType, {
  1242. fabric : {
  1243. type : Material.PolylineGlowType,
  1244. uniforms : {
  1245. color : new Color(0.0, 0.5, 1.0, 1.0),
  1246. glowPower : 0.25
  1247. },
  1248. source : PolylineGlowMaterial
  1249. },
  1250. translucent : true
  1251. });
  1252. /**
  1253. * Gets the name of the polyline outline material.
  1254. * @type {String}
  1255. * @readonly
  1256. */
  1257. Material.PolylineOutlineType = 'PolylineOutline';
  1258. Material._materialCache.addMaterial(Material.PolylineOutlineType, {
  1259. fabric : {
  1260. type : Material.PolylineOutlineType,
  1261. uniforms : {
  1262. color : new Color(1.0, 1.0, 1.0, 1.0),
  1263. outlineColor : new Color(1.0, 0.0, 0.0, 1.0),
  1264. outlineWidth : 1.0
  1265. },
  1266. source : PolylineOutlineMaterial
  1267. },
  1268. translucent : function(material) {
  1269. var uniforms = material.uniforms;
  1270. return (uniforms.color.alpha < 1.0) || (uniforms.outlineColor.alpha < 1.0);
  1271. }
  1272. });
  1273. return Material;
  1274. });