GlobeFS.glsl 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. uniform vec4 u_initialColor;
  2. #if TEXTURE_UNITS > 0
  3. uniform sampler2D u_dayTextures[TEXTURE_UNITS];
  4. uniform vec4 u_dayTextureTranslationAndScale[TEXTURE_UNITS];
  5. uniform bool u_dayTextureUseWebMercatorT[TEXTURE_UNITS];
  6. #ifdef APPLY_ALPHA
  7. uniform float u_dayTextureAlpha[TEXTURE_UNITS];
  8. #endif
  9. #ifdef APPLY_DAY_NIGHT_ALPHA
  10. uniform float u_dayTextureNightAlpha[TEXTURE_UNITS];
  11. uniform float u_dayTextureDayAlpha[TEXTURE_UNITS];
  12. #endif
  13. #ifdef APPLY_SPLIT
  14. uniform float u_dayTextureSplit[TEXTURE_UNITS];
  15. #endif
  16. #ifdef APPLY_BRIGHTNESS
  17. uniform float u_dayTextureBrightness[TEXTURE_UNITS];
  18. #endif
  19. #ifdef APPLY_CONTRAST
  20. uniform float u_dayTextureContrast[TEXTURE_UNITS];
  21. #endif
  22. #ifdef APPLY_HUE
  23. uniform float u_dayTextureHue[TEXTURE_UNITS];
  24. #endif
  25. #ifdef APPLY_SATURATION
  26. uniform float u_dayTextureSaturation[TEXTURE_UNITS];
  27. #endif
  28. #ifdef APPLY_GAMMA
  29. uniform float u_dayTextureOneOverGamma[TEXTURE_UNITS];
  30. #endif
  31. #ifdef APPLY_IMAGERY_CUTOUT
  32. uniform vec4 u_dayTextureCutoutRectangles[TEXTURE_UNITS];
  33. #endif
  34. #ifdef APPLY_COLOR_TO_ALPHA
  35. uniform vec4 u_colorsToAlpha[TEXTURE_UNITS];
  36. #endif
  37. uniform vec4 u_dayTextureTexCoordsRectangle[TEXTURE_UNITS];
  38. #endif
  39. #ifdef SHOW_REFLECTIVE_OCEAN
  40. uniform sampler2D u_waterMask;
  41. uniform vec4 u_waterMaskTranslationAndScale;
  42. uniform float u_zoomedOutOceanSpecularIntensity;
  43. #endif
  44. #ifdef SHOW_OCEAN_WAVES
  45. uniform sampler2D u_oceanNormalMap;
  46. #endif
  47. #if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE)
  48. uniform vec2 u_lightingFadeDistance;
  49. #endif
  50. #ifdef TILE_LIMIT_RECTANGLE
  51. uniform vec4 u_cartographicLimitRectangle;
  52. #endif
  53. #ifdef GROUND_ATMOSPHERE
  54. uniform vec2 u_nightFadeDistance;
  55. #endif
  56. #ifdef ENABLE_CLIPPING_PLANES
  57. uniform highp sampler2D u_clippingPlanes;
  58. uniform mat4 u_clippingPlanesMatrix;
  59. uniform vec4 u_clippingPlanesEdgeStyle;
  60. #endif
  61. #if defined(GROUND_ATMOSPHERE) || defined(FOG) && defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING))
  62. uniform float u_minimumBrightness;
  63. #endif
  64. #ifdef COLOR_CORRECT
  65. uniform vec3 u_hsbShift; // Hue, saturation, brightness
  66. #endif
  67. #ifdef HIGHLIGHT_FILL_TILE
  68. uniform vec4 u_fillHighlightColor;
  69. #endif
  70. #ifdef TRANSLUCENT
  71. uniform vec4 u_frontFaceAlphaByDistance;
  72. uniform vec4 u_backFaceAlphaByDistance;
  73. uniform vec4 u_translucencyRectangle;
  74. #endif
  75. #ifdef UNDERGROUND_COLOR
  76. uniform vec4 u_undergroundColor;
  77. uniform vec4 u_undergroundColorAlphaByDistance;
  78. #endif
  79. #ifdef ENABLE_VERTEX_LIGHTING
  80. uniform float u_lambertDiffuseMultiplier;
  81. #endif
  82. varying vec3 v_positionMC;
  83. varying vec3 v_positionEC;
  84. varying vec3 v_textureCoordinates;
  85. varying vec3 v_normalMC;
  86. varying vec3 v_normalEC;
  87. #ifdef APPLY_MATERIAL
  88. varying float v_height;
  89. varying float v_slope;
  90. varying float v_aspect;
  91. #endif
  92. #if defined(FOG) || defined(GROUND_ATMOSPHERE) || defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT)
  93. varying float v_distance;
  94. #endif
  95. #if defined(GROUND_ATMOSPHERE) || defined(FOG)
  96. varying vec3 v_atmosphereRayleighColor;
  97. varying vec3 v_atmosphereMieColor;
  98. varying float v_atmosphereOpacity;
  99. #endif
  100. #if defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT)
  101. float interpolateByDistance(vec4 nearFarScalar, float distance)
  102. {
  103. float startDistance = nearFarScalar.x;
  104. float startValue = nearFarScalar.y;
  105. float endDistance = nearFarScalar.z;
  106. float endValue = nearFarScalar.w;
  107. float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0);
  108. return mix(startValue, endValue, t);
  109. }
  110. #endif
  111. #if defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT) || defined(APPLY_MATERIAL)
  112. vec4 alphaBlend(vec4 sourceColor, vec4 destinationColor)
  113. {
  114. return sourceColor * vec4(sourceColor.aaa, 1.0) + destinationColor * (1.0 - sourceColor.a);
  115. }
  116. #endif
  117. #ifdef TRANSLUCENT
  118. bool inTranslucencyRectangle()
  119. {
  120. return
  121. v_textureCoordinates.x > u_translucencyRectangle.x &&
  122. v_textureCoordinates.x < u_translucencyRectangle.z &&
  123. v_textureCoordinates.y > u_translucencyRectangle.y &&
  124. v_textureCoordinates.y < u_translucencyRectangle.w;
  125. }
  126. #endif
  127. vec4 sampleAndBlend(
  128. vec4 previousColor,
  129. sampler2D textureToSample,
  130. vec2 tileTextureCoordinates,
  131. vec4 textureCoordinateRectangle,
  132. vec4 textureCoordinateTranslationAndScale,
  133. float textureAlpha,
  134. float textureNightAlpha,
  135. float textureDayAlpha,
  136. float textureBrightness,
  137. float textureContrast,
  138. float textureHue,
  139. float textureSaturation,
  140. float textureOneOverGamma,
  141. float split,
  142. vec4 colorToAlpha,
  143. float nightBlend)
  144. {
  145. // This crazy step stuff sets the alpha to 0.0 if this following condition is true:
  146. // tileTextureCoordinates.s < textureCoordinateRectangle.s ||
  147. // tileTextureCoordinates.s > textureCoordinateRectangle.p ||
  148. // tileTextureCoordinates.t < textureCoordinateRectangle.t ||
  149. // tileTextureCoordinates.t > textureCoordinateRectangle.q
  150. // In other words, the alpha is zero if the fragment is outside the rectangle
  151. // covered by this texture. Would an actual 'if' yield better performance?
  152. vec2 alphaMultiplier = step(textureCoordinateRectangle.st, tileTextureCoordinates);
  153. textureAlpha = textureAlpha * alphaMultiplier.x * alphaMultiplier.y;
  154. alphaMultiplier = step(vec2(0.0), textureCoordinateRectangle.pq - tileTextureCoordinates);
  155. textureAlpha = textureAlpha * alphaMultiplier.x * alphaMultiplier.y;
  156. #if defined(APPLY_DAY_NIGHT_ALPHA) && defined(ENABLE_DAYNIGHT_SHADING)
  157. textureAlpha *= mix(textureDayAlpha, textureNightAlpha, nightBlend);
  158. #endif
  159. vec2 translation = textureCoordinateTranslationAndScale.xy;
  160. vec2 scale = textureCoordinateTranslationAndScale.zw;
  161. vec2 textureCoordinates = tileTextureCoordinates * scale + translation;
  162. vec4 value = texture2D(textureToSample, textureCoordinates);
  163. vec3 color = value.rgb;
  164. float alpha = value.a;
  165. #ifdef APPLY_COLOR_TO_ALPHA
  166. vec3 colorDiff = abs(color.rgb - colorToAlpha.rgb);
  167. colorDiff.r = max(max(colorDiff.r, colorDiff.g), colorDiff.b);
  168. alpha = czm_branchFreeTernary(colorDiff.r < colorToAlpha.a, 0.0, alpha);
  169. #endif
  170. #if !defined(APPLY_GAMMA)
  171. vec4 tempColor = czm_gammaCorrect(vec4(color, alpha));
  172. color = tempColor.rgb;
  173. alpha = tempColor.a;
  174. #else
  175. color = pow(color, vec3(textureOneOverGamma));
  176. #endif
  177. #ifdef APPLY_SPLIT
  178. float splitPosition = czm_splitPosition;
  179. // Split to the left
  180. if (split < 0.0 && gl_FragCoord.x > splitPosition) {
  181. alpha = 0.0;
  182. }
  183. // Split to the right
  184. else if (split > 0.0 && gl_FragCoord.x < splitPosition) {
  185. alpha = 0.0;
  186. }
  187. #endif
  188. #ifdef APPLY_BRIGHTNESS
  189. color = mix(vec3(0.0), color, textureBrightness);
  190. #endif
  191. #ifdef APPLY_CONTRAST
  192. color = mix(vec3(0.5), color, textureContrast);
  193. #endif
  194. #ifdef APPLY_HUE
  195. color = czm_hue(color, textureHue);
  196. #endif
  197. #ifdef APPLY_SATURATION
  198. color = czm_saturation(color, textureSaturation);
  199. #endif
  200. float sourceAlpha = alpha * textureAlpha;
  201. float outAlpha = mix(previousColor.a, 1.0, sourceAlpha);
  202. outAlpha += sign(outAlpha) - 1.0;
  203. vec3 outColor = mix(previousColor.rgb * previousColor.a, color, sourceAlpha) / outAlpha;
  204. // When rendering imagery for a tile in multiple passes,
  205. // some GPU/WebGL implementation combinations will not blend fragments in
  206. // additional passes correctly if their computation includes an unmasked
  207. // divide-by-zero operation,
  208. // even if it's not in the output or if the output has alpha zero.
  209. //
  210. // For example, without sanitization for outAlpha,
  211. // this renders without artifacts:
  212. // if (outAlpha == 0.0) { outColor = vec3(0.0); }
  213. //
  214. // but using czm_branchFreeTernary will cause portions of the tile that are
  215. // alpha-zero in the additional pass to render as black instead of blending
  216. // with the previous pass:
  217. // outColor = czm_branchFreeTernary(outAlpha == 0.0, vec3(0.0), outColor);
  218. //
  219. // So instead, sanitize against divide-by-zero,
  220. // store this state on the sign of outAlpha, and correct on return.
  221. return vec4(outColor, max(outAlpha, 0.0));
  222. }
  223. vec3 colorCorrect(vec3 rgb) {
  224. #ifdef COLOR_CORRECT
  225. // Convert rgb color to hsb
  226. vec3 hsb = czm_RGBToHSB(rgb);
  227. // Perform hsb shift
  228. hsb.x += u_hsbShift.x; // hue
  229. hsb.y = clamp(hsb.y + u_hsbShift.y, 0.0, 1.0); // saturation
  230. hsb.z = hsb.z > czm_epsilon7 ? hsb.z + u_hsbShift.z : 0.0; // brightness
  231. // Convert shifted hsb back to rgb
  232. rgb = czm_HSBToRGB(hsb);
  233. #endif
  234. return rgb;
  235. }
  236. vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates, float nightBlend);
  237. vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float specularMapValue, float fade);
  238. const float fExposure = 2.0;
  239. vec3 computeEllipsoidPosition()
  240. {
  241. float mpp = czm_metersPerPixel(vec4(0.0, 0.0, -czm_currentFrustum.x, 1.0), 1.0);
  242. vec2 xy = gl_FragCoord.xy / czm_viewport.zw * 2.0 - vec2(1.0);
  243. xy *= czm_viewport.zw * mpp * 0.5;
  244. vec3 direction = normalize(vec3(xy, -czm_currentFrustum.x));
  245. czm_ray ray = czm_ray(vec3(0.0), direction);
  246. vec3 ellipsoid_center = czm_view[3].xyz;
  247. czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, ellipsoid_center, czm_ellipsoidInverseRadii);
  248. vec3 ellipsoidPosition = czm_pointAlongRay(ray, intersection.start);
  249. return (czm_inverseView * vec4(ellipsoidPosition, 1.0)).xyz;
  250. }
  251. void main()
  252. {
  253. #ifdef TILE_LIMIT_RECTANGLE
  254. if (v_textureCoordinates.x < u_cartographicLimitRectangle.x || u_cartographicLimitRectangle.z < v_textureCoordinates.x ||
  255. v_textureCoordinates.y < u_cartographicLimitRectangle.y || u_cartographicLimitRectangle.w < v_textureCoordinates.y)
  256. {
  257. discard;
  258. }
  259. #endif
  260. #ifdef ENABLE_CLIPPING_PLANES
  261. float clipDistance = clip(gl_FragCoord, u_clippingPlanes, u_clippingPlanesMatrix);
  262. #endif
  263. #if defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) || defined(HDR)
  264. vec3 normalMC = czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)); // normalized surface normal in model coordinates
  265. vec3 normalEC = czm_normal3D * normalMC; // normalized surface normal in eye coordiantes
  266. #endif
  267. #if defined(APPLY_DAY_NIGHT_ALPHA) && defined(ENABLE_DAYNIGHT_SHADING)
  268. float nightBlend = 1.0 - clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * 5.0, 0.0, 1.0);
  269. #else
  270. float nightBlend = 0.0;
  271. #endif
  272. // The clamp below works around an apparent bug in Chrome Canary v23.0.1241.0
  273. // where the fragment shader sees textures coordinates < 0.0 and > 1.0 for the
  274. // fragments on the edges of tiles even though the vertex shader is outputting
  275. // coordinates strictly in the 0-1 range.
  276. vec4 color = computeDayColor(u_initialColor, clamp(v_textureCoordinates, 0.0, 1.0), nightBlend);
  277. #ifdef SHOW_TILE_BOUNDARIES
  278. if (v_textureCoordinates.x < (1.0/256.0) || v_textureCoordinates.x > (255.0/256.0) ||
  279. v_textureCoordinates.y < (1.0/256.0) || v_textureCoordinates.y > (255.0/256.0))
  280. {
  281. color = vec4(1.0, 0.0, 0.0, 1.0);
  282. }
  283. #endif
  284. #if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE)
  285. float cameraDist;
  286. if (czm_sceneMode == czm_sceneMode2D)
  287. {
  288. cameraDist = max(czm_frustumPlanes.x - czm_frustumPlanes.y, czm_frustumPlanes.w - czm_frustumPlanes.z) * 0.5;
  289. }
  290. else if (czm_sceneMode == czm_sceneModeColumbusView)
  291. {
  292. cameraDist = -czm_view[3].z;
  293. }
  294. else
  295. {
  296. cameraDist = length(czm_view[3]);
  297. }
  298. float fadeOutDist = u_lightingFadeDistance.x;
  299. float fadeInDist = u_lightingFadeDistance.y;
  300. if (czm_sceneMode != czm_sceneMode3D) {
  301. vec3 radii = czm_ellipsoidRadii;
  302. float maxRadii = max(radii.x, max(radii.y, radii.z));
  303. fadeOutDist -= maxRadii;
  304. fadeInDist -= maxRadii;
  305. }
  306. float fade = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.0, 1.0);
  307. #else
  308. float fade = 0.0;
  309. #endif
  310. #ifdef SHOW_REFLECTIVE_OCEAN
  311. vec2 waterMaskTranslation = u_waterMaskTranslationAndScale.xy;
  312. vec2 waterMaskScale = u_waterMaskTranslationAndScale.zw;
  313. vec2 waterMaskTextureCoordinates = v_textureCoordinates.xy * waterMaskScale + waterMaskTranslation;
  314. waterMaskTextureCoordinates.y = 1.0 - waterMaskTextureCoordinates.y;
  315. float mask = texture2D(u_waterMask, waterMaskTextureCoordinates).r;
  316. if (mask > 0.0)
  317. {
  318. mat3 enuToEye = czm_eastNorthUpToEyeCoordinates(v_positionMC, normalEC);
  319. vec2 ellipsoidTextureCoordinates = czm_ellipsoidWgs84TextureCoordinates(normalMC);
  320. vec2 ellipsoidFlippedTextureCoordinates = czm_ellipsoidWgs84TextureCoordinates(normalMC.zyx);
  321. vec2 textureCoordinates = mix(ellipsoidTextureCoordinates, ellipsoidFlippedTextureCoordinates, czm_morphTime * smoothstep(0.9, 0.95, normalMC.z));
  322. color = computeWaterColor(v_positionEC, textureCoordinates, enuToEye, color, mask, fade);
  323. }
  324. #endif
  325. #ifdef APPLY_MATERIAL
  326. czm_materialInput materialInput;
  327. materialInput.st = v_textureCoordinates.st;
  328. materialInput.normalEC = normalize(v_normalEC);
  329. materialInput.positionToEyeEC = -v_positionEC;
  330. materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, normalize(v_normalEC));
  331. materialInput.slope = v_slope;
  332. materialInput.height = v_height;
  333. materialInput.aspect = v_aspect;
  334. czm_material material = czm_getMaterial(materialInput);
  335. vec4 materialColor = vec4(material.diffuse, material.alpha);
  336. color = alphaBlend(materialColor, color);
  337. #endif
  338. #ifdef ENABLE_VERTEX_LIGHTING
  339. float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalize(v_normalEC)) * u_lambertDiffuseMultiplier + 0.3, 0.0, 1.0);
  340. vec4 finalColor = vec4(color.rgb * czm_lightColor * diffuseIntensity, color.a);
  341. #elif defined(ENABLE_DAYNIGHT_SHADING)
  342. float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * 5.0 + 0.3, 0.0, 1.0);
  343. diffuseIntensity = mix(1.0, diffuseIntensity, fade);
  344. vec4 finalColor = vec4(color.rgb * czm_lightColor * diffuseIntensity, color.a);
  345. #else
  346. vec4 finalColor = color;
  347. #endif
  348. #ifdef ENABLE_CLIPPING_PLANES
  349. vec4 clippingPlanesEdgeColor = vec4(1.0);
  350. clippingPlanesEdgeColor.rgb = u_clippingPlanesEdgeStyle.rgb;
  351. float clippingPlanesEdgeWidth = u_clippingPlanesEdgeStyle.a;
  352. if (clipDistance < clippingPlanesEdgeWidth)
  353. {
  354. finalColor = clippingPlanesEdgeColor;
  355. }
  356. #endif
  357. #ifdef HIGHLIGHT_FILL_TILE
  358. finalColor = vec4(mix(finalColor.rgb, u_fillHighlightColor.rgb, u_fillHighlightColor.a), finalColor.a);
  359. #endif
  360. #if defined(DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN)
  361. vec3 atmosphereLightDirection = czm_sunDirectionWC;
  362. #else
  363. vec3 atmosphereLightDirection = czm_lightDirectionWC;
  364. #endif
  365. #if defined(GROUND_ATMOSPHERE) || defined(FOG)
  366. if (!czm_backFacing())
  367. {
  368. bool dynamicLighting = false;
  369. #if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_DAYNIGHT_SHADING) || defined(ENABLE_VERTEX_LIGHTING))
  370. dynamicLighting = true;
  371. #endif
  372. vec3 rayleighColor;
  373. vec3 mieColor;
  374. float opacity;
  375. vec3 positionWC;
  376. vec3 lightDirection;
  377. // When the camera is far away (camera distance > nightFadeOutDistance), the scattering is computed in the fragment shader.
  378. // Otherwise, the scattering is computed in the vertex shader.
  379. #ifdef PER_FRAGMENT_GROUND_ATMOSPHERE
  380. positionWC = computeEllipsoidPosition();
  381. lightDirection = czm_branchFreeTernary(dynamicLighting, atmosphereLightDirection, normalize(positionWC));
  382. computeAtmosphereScattering(
  383. positionWC,
  384. lightDirection,
  385. rayleighColor,
  386. mieColor,
  387. opacity
  388. );
  389. #else
  390. positionWC = v_positionMC;
  391. lightDirection = czm_branchFreeTernary(dynamicLighting, atmosphereLightDirection, normalize(positionWC));
  392. rayleighColor = v_atmosphereRayleighColor;
  393. mieColor = v_atmosphereMieColor;
  394. opacity = v_atmosphereOpacity;
  395. #endif
  396. rayleighColor = colorCorrect(rayleighColor);
  397. mieColor = colorCorrect(mieColor);
  398. vec4 groundAtmosphereColor = computeAtmosphereColor(positionWC, lightDirection, rayleighColor, mieColor, opacity);
  399. // Fog is applied to tiles selected for fog, close to the Earth.
  400. #ifdef FOG
  401. vec3 fogColor = groundAtmosphereColor.rgb;
  402. // If there is lighting, apply that to the fog.
  403. #if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING))
  404. float darken = clamp(dot(normalize(czm_viewerPositionWC), atmosphereLightDirection), u_minimumBrightness, 1.0);
  405. fogColor *= darken;
  406. #endif
  407. #ifndef HDR
  408. fogColor.rgb = czm_acesTonemapping(fogColor.rgb);
  409. fogColor.rgb = czm_inverseGamma(fogColor.rgb);
  410. #endif
  411. const float modifier = 0.15;
  412. finalColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor.rgb, modifier), finalColor.a);
  413. #else
  414. // The transmittance is based on optical depth i.e. the length of segment of the ray inside the atmosphere.
  415. // This value is larger near the "circumference", as it is further away from the camera. We use it to
  416. // brighten up that area of the ground atmosphere.
  417. const float transmittanceModifier = 0.5;
  418. float transmittance = transmittanceModifier + clamp(1.0 - groundAtmosphereColor.a, 0.0, 1.0);
  419. vec3 finalAtmosphereColor = finalColor.rgb + groundAtmosphereColor.rgb * transmittance;
  420. #if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING))
  421. float fadeInDist = u_nightFadeDistance.x;
  422. float fadeOutDist = u_nightFadeDistance.y;
  423. float sunlitAtmosphereIntensity = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.05, 1.0);
  424. float darken = clamp(dot(normalize(positionWC), atmosphereLightDirection), 0.0, 1.0);
  425. vec3 darkenendGroundAtmosphereColor = mix(groundAtmosphereColor.rgb, finalAtmosphereColor.rgb, darken);
  426. finalAtmosphereColor = mix(darkenendGroundAtmosphereColor, finalAtmosphereColor, sunlitAtmosphereIntensity);
  427. #endif
  428. #ifndef HDR
  429. finalAtmosphereColor.rgb = vec3(1.0) - exp(-fExposure * finalAtmosphereColor.rgb);
  430. #else
  431. finalAtmosphereColor.rgb = czm_saturation(finalAtmosphereColor.rgb, 1.6);
  432. #endif
  433. finalColor.rgb = mix(finalColor.rgb, finalAtmosphereColor.rgb, fade);
  434. #endif
  435. }
  436. #endif
  437. #ifdef UNDERGROUND_COLOR
  438. if (czm_backFacing())
  439. {
  440. float distanceFromEllipsoid = max(czm_eyeHeight, 0.0);
  441. float distance = max(v_distance - distanceFromEllipsoid, 0.0);
  442. float blendAmount = interpolateByDistance(u_undergroundColorAlphaByDistance, distance);
  443. vec4 undergroundColor = vec4(u_undergroundColor.rgb, u_undergroundColor.a * blendAmount);
  444. finalColor = alphaBlend(undergroundColor, finalColor);
  445. }
  446. #endif
  447. #ifdef TRANSLUCENT
  448. if (inTranslucencyRectangle())
  449. {
  450. vec4 alphaByDistance = gl_FrontFacing ? u_frontFaceAlphaByDistance : u_backFaceAlphaByDistance;
  451. finalColor.a *= interpolateByDistance(alphaByDistance, v_distance);
  452. }
  453. #endif
  454. gl_FragColor = finalColor;
  455. }
  456. #ifdef SHOW_REFLECTIVE_OCEAN
  457. float waveFade(float edge0, float edge1, float x)
  458. {
  459. float y = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
  460. return pow(1.0 - y, 5.0);
  461. }
  462. float linearFade(float edge0, float edge1, float x)
  463. {
  464. return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
  465. }
  466. // Based on water rendering by Jonas Wagner:
  467. // http://29a.ch/2012/7/19/webgl-terrain-rendering-water-fog
  468. // low altitude wave settings
  469. const float oceanFrequencyLowAltitude = 825000.0;
  470. const float oceanAnimationSpeedLowAltitude = 0.004;
  471. const float oceanOneOverAmplitudeLowAltitude = 1.0 / 2.0;
  472. const float oceanSpecularIntensity = 0.5;
  473. // high altitude wave settings
  474. const float oceanFrequencyHighAltitude = 125000.0;
  475. const float oceanAnimationSpeedHighAltitude = 0.008;
  476. const float oceanOneOverAmplitudeHighAltitude = 1.0 / 2.0;
  477. vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float maskValue, float fade)
  478. {
  479. vec3 positionToEyeEC = -positionEyeCoordinates;
  480. float positionToEyeECLength = length(positionToEyeEC);
  481. // The double normalize below works around a bug in Firefox on Android devices.
  482. vec3 normalizedPositionToEyeEC = normalize(normalize(positionToEyeEC));
  483. // Fade out the waves as the camera moves far from the surface.
  484. float waveIntensity = waveFade(70000.0, 1000000.0, positionToEyeECLength);
  485. #ifdef SHOW_OCEAN_WAVES
  486. // high altitude waves
  487. float time = czm_frameNumber * oceanAnimationSpeedHighAltitude;
  488. vec4 noise = czm_getWaterNoise(u_oceanNormalMap, textureCoordinates * oceanFrequencyHighAltitude, time, 0.0);
  489. vec3 normalTangentSpaceHighAltitude = vec3(noise.xy, noise.z * oceanOneOverAmplitudeHighAltitude);
  490. // low altitude waves
  491. time = czm_frameNumber * oceanAnimationSpeedLowAltitude;
  492. noise = czm_getWaterNoise(u_oceanNormalMap, textureCoordinates * oceanFrequencyLowAltitude, time, 0.0);
  493. vec3 normalTangentSpaceLowAltitude = vec3(noise.xy, noise.z * oceanOneOverAmplitudeLowAltitude);
  494. // blend the 2 wave layers based on distance to surface
  495. float highAltitudeFade = linearFade(0.0, 60000.0, positionToEyeECLength);
  496. float lowAltitudeFade = 1.0 - linearFade(20000.0, 60000.0, positionToEyeECLength);
  497. vec3 normalTangentSpace =
  498. (highAltitudeFade * normalTangentSpaceHighAltitude) +
  499. (lowAltitudeFade * normalTangentSpaceLowAltitude);
  500. normalTangentSpace = normalize(normalTangentSpace);
  501. // fade out the normal perturbation as we move farther from the water surface
  502. normalTangentSpace.xy *= waveIntensity;
  503. normalTangentSpace = normalize(normalTangentSpace);
  504. #else
  505. vec3 normalTangentSpace = vec3(0.0, 0.0, 1.0);
  506. #endif
  507. vec3 normalEC = enuToEye * normalTangentSpace;
  508. const vec3 waveHighlightColor = vec3(0.3, 0.45, 0.6);
  509. // Use diffuse light to highlight the waves
  510. float diffuseIntensity = czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * maskValue;
  511. vec3 diffuseHighlight = waveHighlightColor * diffuseIntensity * (1.0 - fade);
  512. #ifdef SHOW_OCEAN_WAVES
  513. // Where diffuse light is low or non-existent, use wave highlights based solely on
  514. // the wave bumpiness and no particular light direction.
  515. float tsPerturbationRatio = normalTangentSpace.z;
  516. vec3 nonDiffuseHighlight = mix(waveHighlightColor * 5.0 * (1.0 - tsPerturbationRatio), vec3(0.0), diffuseIntensity);
  517. #else
  518. vec3 nonDiffuseHighlight = vec3(0.0);
  519. #endif
  520. // Add specular highlights in 3D, and in all modes when zoomed in.
  521. float specularIntensity = czm_getSpecular(czm_lightDirectionEC, normalizedPositionToEyeEC, normalEC, 10.0);
  522. float surfaceReflectance = mix(0.0, mix(u_zoomedOutOceanSpecularIntensity, oceanSpecularIntensity, waveIntensity), maskValue);
  523. float specular = specularIntensity * surfaceReflectance;
  524. #ifdef HDR
  525. specular *= 1.4;
  526. float e = 0.2;
  527. float d = 3.3;
  528. float c = 1.7;
  529. vec3 color = imageryColor.rgb + (c * (vec3(e) + imageryColor.rgb * d) * (diffuseHighlight + nonDiffuseHighlight + specular));
  530. #else
  531. vec3 color = imageryColor.rgb + diffuseHighlight + nonDiffuseHighlight + specular;
  532. #endif
  533. return vec4(color, imageryColor.a);
  534. }
  535. #endif // #ifdef SHOW_REFLECTIVE_OCEAN