GlobeSurfaceShaderSet.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. import defined from "../Core/defined.js";
  2. import destroyObject from "../Core/destroyObject.js";
  3. import TerrainQuantization from "../Core/TerrainQuantization.js";
  4. import ShaderProgram from "../Renderer/ShaderProgram.js";
  5. import getClippingFunction from "./getClippingFunction.js";
  6. import SceneMode from "./SceneMode.js";
  7. function GlobeSurfaceShader(
  8. numberOfDayTextures,
  9. flags,
  10. material,
  11. shaderProgram,
  12. clippingShaderState
  13. ) {
  14. this.numberOfDayTextures = numberOfDayTextures;
  15. this.flags = flags;
  16. this.material = material;
  17. this.shaderProgram = shaderProgram;
  18. this.clippingShaderState = clippingShaderState;
  19. }
  20. /**
  21. * Manages the shaders used to shade the surface of a {@link Globe}.
  22. *
  23. * @alias GlobeSurfaceShaderSet
  24. * @private
  25. */
  26. function GlobeSurfaceShaderSet() {
  27. this.baseVertexShaderSource = undefined;
  28. this.baseFragmentShaderSource = undefined;
  29. this._shadersByTexturesFlags = [];
  30. this.material = undefined;
  31. }
  32. function getPositionMode(sceneMode) {
  33. var getPosition3DMode =
  34. "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPosition3DMode(position, height, textureCoordinates); }";
  35. var getPositionColumbusViewAnd2DMode =
  36. "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPositionColumbusViewMode(position, height, textureCoordinates); }";
  37. var getPositionMorphingMode =
  38. "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPositionMorphingMode(position, height, textureCoordinates); }";
  39. var positionMode;
  40. switch (sceneMode) {
  41. case SceneMode.SCENE3D:
  42. positionMode = getPosition3DMode;
  43. break;
  44. case SceneMode.SCENE2D:
  45. case SceneMode.COLUMBUS_VIEW:
  46. positionMode = getPositionColumbusViewAnd2DMode;
  47. break;
  48. case SceneMode.MORPHING:
  49. positionMode = getPositionMorphingMode;
  50. break;
  51. }
  52. return positionMode;
  53. }
  54. function get2DYPositionFraction(useWebMercatorProjection) {
  55. var get2DYPositionFractionGeographicProjection =
  56. "float get2DYPositionFraction(vec2 textureCoordinates) { return get2DGeographicYPositionFraction(textureCoordinates); }";
  57. var get2DYPositionFractionMercatorProjection =
  58. "float get2DYPositionFraction(vec2 textureCoordinates) { return get2DMercatorYPositionFraction(textureCoordinates); }";
  59. return useWebMercatorProjection
  60. ? get2DYPositionFractionMercatorProjection
  61. : get2DYPositionFractionGeographicProjection;
  62. }
  63. GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
  64. var frameState = options.frameState;
  65. var surfaceTile = options.surfaceTile;
  66. var numberOfDayTextures = options.numberOfDayTextures;
  67. var applyBrightness = options.applyBrightness;
  68. var applyContrast = options.applyContrast;
  69. var applyHue = options.applyHue;
  70. var applySaturation = options.applySaturation;
  71. var applyGamma = options.applyGamma;
  72. var applyAlpha = options.applyAlpha;
  73. var applyDayNightAlpha = options.applyDayNightAlpha;
  74. var applySplit = options.applySplit;
  75. var showReflectiveOcean = options.showReflectiveOcean;
  76. var showOceanWaves = options.showOceanWaves;
  77. var enableLighting = options.enableLighting;
  78. var dynamicAtmosphereLighting = options.dynamicAtmosphereLighting;
  79. var dynamicAtmosphereLightingFromSun =
  80. options.dynamicAtmosphereLightingFromSun;
  81. var showGroundAtmosphere = options.showGroundAtmosphere;
  82. var perFragmentGroundAtmosphere = options.perFragmentGroundAtmosphere;
  83. var hasVertexNormals = options.hasVertexNormals;
  84. var useWebMercatorProjection = options.useWebMercatorProjection;
  85. var enableFog = options.enableFog;
  86. var enableClippingPlanes = options.enableClippingPlanes;
  87. var clippingPlanes = options.clippingPlanes;
  88. var clippedByBoundaries = options.clippedByBoundaries;
  89. var hasImageryLayerCutout = options.hasImageryLayerCutout;
  90. var colorCorrect = options.colorCorrect;
  91. var highlightFillTile = options.highlightFillTile;
  92. var colorToAlpha = options.colorToAlpha;
  93. var showUndergroundColor = options.showUndergroundColor;
  94. var translucent = options.translucent;
  95. var quantization = 0;
  96. var quantizationDefine = "";
  97. var mesh = surfaceTile.renderedMesh;
  98. var terrainEncoding = mesh.encoding;
  99. var quantizationMode = terrainEncoding.quantization;
  100. if (quantizationMode === TerrainQuantization.BITS12) {
  101. quantization = 1;
  102. quantizationDefine = "QUANTIZATION_BITS12";
  103. }
  104. var cartographicLimitRectangleFlag = 0;
  105. var cartographicLimitRectangleDefine = "";
  106. if (clippedByBoundaries) {
  107. cartographicLimitRectangleFlag = 1;
  108. cartographicLimitRectangleDefine = "TILE_LIMIT_RECTANGLE";
  109. }
  110. var imageryCutoutFlag = 0;
  111. var imageryCutoutDefine = "";
  112. if (hasImageryLayerCutout) {
  113. imageryCutoutFlag = 1;
  114. imageryCutoutDefine = "APPLY_IMAGERY_CUTOUT";
  115. }
  116. var sceneMode = frameState.mode;
  117. var flags =
  118. sceneMode |
  119. (applyBrightness << 2) |
  120. (applyContrast << 3) |
  121. (applyHue << 4) |
  122. (applySaturation << 5) |
  123. (applyGamma << 6) |
  124. (applyAlpha << 7) |
  125. (showReflectiveOcean << 8) |
  126. (showOceanWaves << 9) |
  127. (enableLighting << 10) |
  128. (dynamicAtmosphereLighting << 11) |
  129. (dynamicAtmosphereLightingFromSun << 12) |
  130. (showGroundAtmosphere << 13) |
  131. (perFragmentGroundAtmosphere << 14) |
  132. (hasVertexNormals << 15) |
  133. (useWebMercatorProjection << 16) |
  134. (enableFog << 17) |
  135. (quantization << 18) |
  136. (applySplit << 19) |
  137. (enableClippingPlanes << 20) |
  138. (cartographicLimitRectangleFlag << 21) |
  139. (imageryCutoutFlag << 22) |
  140. (colorCorrect << 23) |
  141. (highlightFillTile << 24) |
  142. (colorToAlpha << 25) |
  143. (showUndergroundColor << 26) |
  144. (translucent << 27) |
  145. (applyDayNightAlpha << 28);
  146. var currentClippingShaderState = 0;
  147. if (defined(clippingPlanes) && clippingPlanes.length > 0) {
  148. currentClippingShaderState = enableClippingPlanes
  149. ? clippingPlanes.clippingPlanesState
  150. : 0;
  151. }
  152. var surfaceShader = surfaceTile.surfaceShader;
  153. if (
  154. defined(surfaceShader) &&
  155. surfaceShader.numberOfDayTextures === numberOfDayTextures &&
  156. surfaceShader.flags === flags &&
  157. surfaceShader.material === this.material &&
  158. surfaceShader.clippingShaderState === currentClippingShaderState
  159. ) {
  160. return surfaceShader.shaderProgram;
  161. }
  162. // New tile, or tile changed number of textures, flags, or clipping planes
  163. var shadersByFlags = this._shadersByTexturesFlags[numberOfDayTextures];
  164. if (!defined(shadersByFlags)) {
  165. shadersByFlags = this._shadersByTexturesFlags[numberOfDayTextures] = [];
  166. }
  167. surfaceShader = shadersByFlags[flags];
  168. if (
  169. !defined(surfaceShader) ||
  170. surfaceShader.material !== this.material ||
  171. surfaceShader.clippingShaderState !== currentClippingShaderState
  172. ) {
  173. // Cache miss - we've never seen this combination of numberOfDayTextures and flags before.
  174. var vs = this.baseVertexShaderSource.clone();
  175. var fs = this.baseFragmentShaderSource.clone();
  176. if (currentClippingShaderState !== 0) {
  177. fs.sources.unshift(
  178. getClippingFunction(clippingPlanes, frameState.context)
  179. ); // Need to go before GlobeFS
  180. }
  181. vs.defines.push(quantizationDefine);
  182. fs.defines.push(
  183. "TEXTURE_UNITS " + numberOfDayTextures,
  184. cartographicLimitRectangleDefine,
  185. imageryCutoutDefine
  186. );
  187. if (applyBrightness) {
  188. fs.defines.push("APPLY_BRIGHTNESS");
  189. }
  190. if (applyContrast) {
  191. fs.defines.push("APPLY_CONTRAST");
  192. }
  193. if (applyHue) {
  194. fs.defines.push("APPLY_HUE");
  195. }
  196. if (applySaturation) {
  197. fs.defines.push("APPLY_SATURATION");
  198. }
  199. if (applyGamma) {
  200. fs.defines.push("APPLY_GAMMA");
  201. }
  202. if (applyAlpha) {
  203. fs.defines.push("APPLY_ALPHA");
  204. }
  205. if (applyDayNightAlpha) {
  206. fs.defines.push("APPLY_DAY_NIGHT_ALPHA");
  207. }
  208. if (showReflectiveOcean) {
  209. fs.defines.push("SHOW_REFLECTIVE_OCEAN");
  210. vs.defines.push("SHOW_REFLECTIVE_OCEAN");
  211. }
  212. if (showOceanWaves) {
  213. fs.defines.push("SHOW_OCEAN_WAVES");
  214. }
  215. if (colorToAlpha) {
  216. fs.defines.push("APPLY_COLOR_TO_ALPHA");
  217. }
  218. if (showUndergroundColor) {
  219. vs.defines.push("UNDERGROUND_COLOR");
  220. fs.defines.push("UNDERGROUND_COLOR");
  221. }
  222. if (translucent) {
  223. vs.defines.push("TRANSLUCENT");
  224. fs.defines.push("TRANSLUCENT");
  225. }
  226. if (enableLighting) {
  227. if (hasVertexNormals) {
  228. vs.defines.push("ENABLE_VERTEX_LIGHTING");
  229. fs.defines.push("ENABLE_VERTEX_LIGHTING");
  230. } else {
  231. vs.defines.push("ENABLE_DAYNIGHT_SHADING");
  232. fs.defines.push("ENABLE_DAYNIGHT_SHADING");
  233. }
  234. }
  235. if (dynamicAtmosphereLighting) {
  236. fs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING");
  237. if (dynamicAtmosphereLightingFromSun) {
  238. fs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN");
  239. }
  240. }
  241. if (showGroundAtmosphere) {
  242. vs.defines.push("GROUND_ATMOSPHERE");
  243. fs.defines.push("GROUND_ATMOSPHERE");
  244. if (perFragmentGroundAtmosphere) {
  245. fs.defines.push("PER_FRAGMENT_GROUND_ATMOSPHERE");
  246. }
  247. }
  248. vs.defines.push("INCLUDE_WEB_MERCATOR_Y");
  249. fs.defines.push("INCLUDE_WEB_MERCATOR_Y");
  250. if (enableFog) {
  251. vs.defines.push("FOG");
  252. fs.defines.push("FOG");
  253. }
  254. if (applySplit) {
  255. fs.defines.push("APPLY_SPLIT");
  256. }
  257. if (enableClippingPlanes) {
  258. fs.defines.push("ENABLE_CLIPPING_PLANES");
  259. }
  260. if (colorCorrect) {
  261. fs.defines.push("COLOR_CORRECT");
  262. }
  263. if (highlightFillTile) {
  264. fs.defines.push("HIGHLIGHT_FILL_TILE");
  265. }
  266. var computeDayColor =
  267. "\
  268. vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates, float nightBlend)\n\
  269. {\n\
  270. vec4 color = initialColor;\n";
  271. if (hasImageryLayerCutout) {
  272. computeDayColor +=
  273. "\
  274. vec4 cutoutAndColorResult;\n\
  275. bool texelUnclipped;\n";
  276. }
  277. for (var i = 0; i < numberOfDayTextures; ++i) {
  278. if (hasImageryLayerCutout) {
  279. computeDayColor +=
  280. "\
  281. cutoutAndColorResult = u_dayTextureCutoutRectangles[" +
  282. i +
  283. "];\n\
  284. texelUnclipped = v_textureCoordinates.x < cutoutAndColorResult.x || cutoutAndColorResult.z < v_textureCoordinates.x || v_textureCoordinates.y < cutoutAndColorResult.y || cutoutAndColorResult.w < v_textureCoordinates.y;\n\
  285. cutoutAndColorResult = sampleAndBlend(\n";
  286. } else {
  287. computeDayColor += "\
  288. color = sampleAndBlend(\n";
  289. }
  290. computeDayColor +=
  291. "\
  292. color,\n\
  293. u_dayTextures[" +
  294. i +
  295. "],\n\
  296. u_dayTextureUseWebMercatorT[" +
  297. i +
  298. "] ? textureCoordinates.xz : textureCoordinates.xy,\n\
  299. u_dayTextureTexCoordsRectangle[" +
  300. i +
  301. "],\n\
  302. u_dayTextureTranslationAndScale[" +
  303. i +
  304. "],\n\
  305. " +
  306. (applyAlpha ? "u_dayTextureAlpha[" + i + "]" : "1.0") +
  307. ",\n\
  308. " +
  309. (applyDayNightAlpha ? "u_dayTextureNightAlpha[" + i + "]" : "1.0") +
  310. ",\n" +
  311. (applyDayNightAlpha ? "u_dayTextureDayAlpha[" + i + "]" : "1.0") +
  312. ",\n" +
  313. (applyBrightness ? "u_dayTextureBrightness[" + i + "]" : "0.0") +
  314. ",\n\
  315. " +
  316. (applyContrast ? "u_dayTextureContrast[" + i + "]" : "0.0") +
  317. ",\n\
  318. " +
  319. (applyHue ? "u_dayTextureHue[" + i + "]" : "0.0") +
  320. ",\n\
  321. " +
  322. (applySaturation ? "u_dayTextureSaturation[" + i + "]" : "0.0") +
  323. ",\n\
  324. " +
  325. (applyGamma ? "u_dayTextureOneOverGamma[" + i + "]" : "0.0") +
  326. ",\n\
  327. " +
  328. (applySplit ? "u_dayTextureSplit[" + i + "]" : "0.0") +
  329. ",\n\
  330. " +
  331. (colorToAlpha ? "u_colorsToAlpha[" + i + "]" : "vec4(0.0)") +
  332. ",\n\
  333. nightBlend\
  334. );\n";
  335. if (hasImageryLayerCutout) {
  336. computeDayColor +=
  337. "\
  338. color = czm_branchFreeTernary(texelUnclipped, cutoutAndColorResult, color);\n";
  339. }
  340. }
  341. computeDayColor += "\
  342. return color;\n\
  343. }";
  344. fs.sources.push(computeDayColor);
  345. vs.sources.push(getPositionMode(sceneMode));
  346. vs.sources.push(get2DYPositionFraction(useWebMercatorProjection));
  347. var shader = ShaderProgram.fromCache({
  348. context: frameState.context,
  349. vertexShaderSource: vs,
  350. fragmentShaderSource: fs,
  351. attributeLocations: terrainEncoding.getAttributeLocations(),
  352. });
  353. surfaceShader = shadersByFlags[flags] = new GlobeSurfaceShader(
  354. numberOfDayTextures,
  355. flags,
  356. this.material,
  357. shader,
  358. currentClippingShaderState
  359. );
  360. }
  361. surfaceTile.surfaceShader = surfaceShader;
  362. return surfaceShader.shaderProgram;
  363. };
  364. GlobeSurfaceShaderSet.prototype.destroy = function () {
  365. var flags;
  366. var shader;
  367. var shadersByTexturesFlags = this._shadersByTexturesFlags;
  368. for (var textureCount in shadersByTexturesFlags) {
  369. if (shadersByTexturesFlags.hasOwnProperty(textureCount)) {
  370. var shadersByFlags = shadersByTexturesFlags[textureCount];
  371. if (!defined(shadersByFlags)) {
  372. continue;
  373. }
  374. for (flags in shadersByFlags) {
  375. if (shadersByFlags.hasOwnProperty(flags)) {
  376. shader = shadersByFlags[flags];
  377. if (defined(shader)) {
  378. shader.shaderProgram.destroy();
  379. }
  380. }
  381. }
  382. }
  383. }
  384. return destroyObject(this);
  385. };
  386. export default GlobeSurfaceShaderSet;