GlobeSurfaceShaderSet.js 14 KB

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