GlobeFS.glsl 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  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(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. varying vec3 v_positionMC;
  80. varying vec3 v_positionEC;
  81. varying vec3 v_textureCoordinates;
  82. varying vec3 v_normalMC;
  83. varying vec3 v_normalEC;
  84. #ifdef APPLY_MATERIAL
  85. varying float v_height;
  86. varying float v_slope;
  87. varying float v_aspect;
  88. #endif
  89. #if defined(FOG) || defined(GROUND_ATMOSPHERE) || defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT)
  90. varying float v_distance;
  91. #endif
  92. #if defined(FOG) || defined(GROUND_ATMOSPHERE)
  93. varying vec3 v_fogRayleighColor;
  94. varying vec3 v_fogMieColor;
  95. #endif
  96. #ifdef GROUND_ATMOSPHERE
  97. varying vec3 v_rayleighColor;
  98. varying vec3 v_mieColor;
  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_imagerySplitPosition;
  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. #ifdef GROUND_ATMOSPHERE
  239. vec3 computeGroundAtmosphereColor(vec3 fogColor, vec4 finalColor, vec3 atmosphereLightDirection, float cameraDist);
  240. #endif
  241. const float fExposure = 2.0;
  242. void main()
  243. {
  244. #ifdef TILE_LIMIT_RECTANGLE
  245. if (v_textureCoordinates.x < u_cartographicLimitRectangle.x || u_cartographicLimitRectangle.z < v_textureCoordinates.x ||
  246. v_textureCoordinates.y < u_cartographicLimitRectangle.y || u_cartographicLimitRectangle.w < v_textureCoordinates.y)
  247. {
  248. discard;
  249. }
  250. #endif
  251. #ifdef ENABLE_CLIPPING_PLANES
  252. float clipDistance = clip(gl_FragCoord, u_clippingPlanes, u_clippingPlanesMatrix);
  253. #endif
  254. #if defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) || defined(HDR)
  255. vec3 normalMC = czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)); // normalized surface normal in model coordinates
  256. vec3 normalEC = czm_normal3D * normalMC; // normalized surface normal in eye coordiantes
  257. #endif
  258. #if defined(APPLY_DAY_NIGHT_ALPHA) && defined(ENABLE_DAYNIGHT_SHADING)
  259. float nightBlend = 1.0 - clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * 5.0, 0.0, 1.0);
  260. #else
  261. float nightBlend = 0.0;
  262. #endif
  263. // The clamp below works around an apparent bug in Chrome Canary v23.0.1241.0
  264. // where the fragment shader sees textures coordinates < 0.0 and > 1.0 for the
  265. // fragments on the edges of tiles even though the vertex shader is outputting
  266. // coordinates strictly in the 0-1 range.
  267. vec4 color = computeDayColor(u_initialColor, clamp(v_textureCoordinates, 0.0, 1.0), nightBlend);
  268. #ifdef SHOW_TILE_BOUNDARIES
  269. if (v_textureCoordinates.x < (1.0/256.0) || v_textureCoordinates.x > (255.0/256.0) ||
  270. v_textureCoordinates.y < (1.0/256.0) || v_textureCoordinates.y > (255.0/256.0))
  271. {
  272. color = vec4(1.0, 0.0, 0.0, 1.0);
  273. }
  274. #endif
  275. #if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE)
  276. float cameraDist;
  277. if (czm_sceneMode == czm_sceneMode2D)
  278. {
  279. cameraDist = max(czm_frustumPlanes.x - czm_frustumPlanes.y, czm_frustumPlanes.w - czm_frustumPlanes.z) * 0.5;
  280. }
  281. else if (czm_sceneMode == czm_sceneModeColumbusView)
  282. {
  283. cameraDist = -czm_view[3].z;
  284. }
  285. else
  286. {
  287. cameraDist = length(czm_view[3]);
  288. }
  289. float fadeOutDist = u_lightingFadeDistance.x;
  290. float fadeInDist = u_lightingFadeDistance.y;
  291. if (czm_sceneMode != czm_sceneMode3D) {
  292. vec3 radii = czm_ellipsoidRadii;
  293. float maxRadii = max(radii.x, max(radii.y, radii.z));
  294. fadeOutDist -= maxRadii;
  295. fadeInDist -= maxRadii;
  296. }
  297. float fade = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.0, 1.0);
  298. #else
  299. float fade = 0.0;
  300. #endif
  301. #ifdef SHOW_REFLECTIVE_OCEAN
  302. vec2 waterMaskTranslation = u_waterMaskTranslationAndScale.xy;
  303. vec2 waterMaskScale = u_waterMaskTranslationAndScale.zw;
  304. vec2 waterMaskTextureCoordinates = v_textureCoordinates.xy * waterMaskScale + waterMaskTranslation;
  305. waterMaskTextureCoordinates.y = 1.0 - waterMaskTextureCoordinates.y;
  306. float mask = texture2D(u_waterMask, waterMaskTextureCoordinates).r;
  307. if (mask > 0.0)
  308. {
  309. mat3 enuToEye = czm_eastNorthUpToEyeCoordinates(v_positionMC, normalEC);
  310. vec2 ellipsoidTextureCoordinates = czm_ellipsoidWgs84TextureCoordinates(normalMC);
  311. vec2 ellipsoidFlippedTextureCoordinates = czm_ellipsoidWgs84TextureCoordinates(normalMC.zyx);
  312. vec2 textureCoordinates = mix(ellipsoidTextureCoordinates, ellipsoidFlippedTextureCoordinates, czm_morphTime * smoothstep(0.9, 0.95, normalMC.z));
  313. color = computeWaterColor(v_positionEC, textureCoordinates, enuToEye, color, mask, fade);
  314. }
  315. #endif
  316. #ifdef APPLY_MATERIAL
  317. czm_materialInput materialInput;
  318. materialInput.st = v_textureCoordinates.st;
  319. materialInput.normalEC = normalize(v_normalEC);
  320. materialInput.slope = v_slope;
  321. materialInput.height = v_height;
  322. materialInput.aspect = v_aspect;
  323. czm_material material = czm_getMaterial(materialInput);
  324. vec4 materialColor = vec4(material.diffuse, material.alpha);
  325. color = alphaBlend(materialColor, color);
  326. #endif
  327. #ifdef ENABLE_VERTEX_LIGHTING
  328. float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalize(v_normalEC)) * 0.9 + 0.3, 0.0, 1.0);
  329. vec4 finalColor = vec4(color.rgb * czm_lightColor * diffuseIntensity, color.a);
  330. #elif defined(ENABLE_DAYNIGHT_SHADING)
  331. float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * 5.0 + 0.3, 0.0, 1.0);
  332. diffuseIntensity = mix(1.0, diffuseIntensity, fade);
  333. vec4 finalColor = vec4(color.rgb * czm_lightColor * diffuseIntensity, color.a);
  334. #else
  335. vec4 finalColor = color;
  336. #endif
  337. #ifdef ENABLE_CLIPPING_PLANES
  338. vec4 clippingPlanesEdgeColor = vec4(1.0);
  339. clippingPlanesEdgeColor.rgb = u_clippingPlanesEdgeStyle.rgb;
  340. float clippingPlanesEdgeWidth = u_clippingPlanesEdgeStyle.a;
  341. if (clipDistance < clippingPlanesEdgeWidth)
  342. {
  343. finalColor = clippingPlanesEdgeColor;
  344. }
  345. #endif
  346. #ifdef HIGHLIGHT_FILL_TILE
  347. finalColor = vec4(mix(finalColor.rgb, u_fillHighlightColor.rgb, u_fillHighlightColor.a), finalColor.a);
  348. #endif
  349. #if defined(FOG) || defined(GROUND_ATMOSPHERE)
  350. vec3 fogColor = colorCorrect(v_fogMieColor) + finalColor.rgb * colorCorrect(v_fogRayleighColor);
  351. #ifndef HDR
  352. fogColor = vec3(1.0) - exp(-fExposure * fogColor);
  353. #endif
  354. #endif
  355. #if defined(DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN)
  356. vec3 atmosphereLightDirection = czm_sunDirectionWC;
  357. #else
  358. vec3 atmosphereLightDirection = czm_lightDirectionWC;
  359. #endif
  360. #ifdef FOG
  361. #if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING))
  362. float darken = clamp(dot(normalize(czm_viewerPositionWC), atmosphereLightDirection), u_minimumBrightness, 1.0);
  363. fogColor *= darken;
  364. #endif
  365. #ifdef HDR
  366. const float modifier = 0.15;
  367. finalColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor, modifier), finalColor.a);
  368. #else
  369. finalColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor), finalColor.a);
  370. #endif
  371. #endif
  372. #ifdef GROUND_ATMOSPHERE
  373. if (!czm_backFacing())
  374. {
  375. vec3 groundAtmosphereColor = computeGroundAtmosphereColor(fogColor, finalColor, atmosphereLightDirection, cameraDist);
  376. finalColor = vec4(mix(finalColor.rgb, groundAtmosphereColor, fade), finalColor.a);
  377. }
  378. #endif
  379. #ifdef UNDERGROUND_COLOR
  380. if (czm_backFacing())
  381. {
  382. float distanceFromEllipsoid = max(czm_eyeHeight, 0.0);
  383. float distance = max(v_distance - distanceFromEllipsoid, 0.0);
  384. float blendAmount = interpolateByDistance(u_undergroundColorAlphaByDistance, distance);
  385. vec4 undergroundColor = vec4(u_undergroundColor.rgb, u_undergroundColor.a * blendAmount);
  386. finalColor = alphaBlend(undergroundColor, finalColor);
  387. }
  388. #endif
  389. #ifdef TRANSLUCENT
  390. if (inTranslucencyRectangle())
  391. {
  392. vec4 alphaByDistance = gl_FrontFacing ? u_frontFaceAlphaByDistance : u_backFaceAlphaByDistance;
  393. finalColor.a *= interpolateByDistance(alphaByDistance, v_distance);
  394. }
  395. #endif
  396. gl_FragColor = finalColor;
  397. }
  398. #ifdef GROUND_ATMOSPHERE
  399. vec3 computeGroundAtmosphereColor(vec3 fogColor, vec4 finalColor, vec3 atmosphereLightDirection, float cameraDist)
  400. {
  401. #if defined(PER_FRAGMENT_GROUND_ATMOSPHERE) && defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_DAYNIGHT_SHADING) || defined(ENABLE_VERTEX_LIGHTING))
  402. float mpp = czm_metersPerPixel(vec4(0.0, 0.0, -czm_currentFrustum.x, 1.0), 1.0);
  403. vec2 xy = gl_FragCoord.xy / czm_viewport.zw * 2.0 - vec2(1.0);
  404. xy *= czm_viewport.zw * mpp * 0.5;
  405. vec3 direction = normalize(vec3(xy, -czm_currentFrustum.x));
  406. czm_ray ray = czm_ray(vec3(0.0), direction);
  407. vec3 ellipsoid_center = czm_view[3].xyz;
  408. czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, ellipsoid_center, czm_ellipsoidInverseRadii);
  409. vec3 ellipsoidPosition = czm_pointAlongRay(ray, intersection.start);
  410. ellipsoidPosition = (czm_inverseView * vec4(ellipsoidPosition, 1.0)).xyz;
  411. AtmosphereColor atmosColor = computeGroundAtmosphereFromSpace(ellipsoidPosition, true, atmosphereLightDirection);
  412. vec3 groundAtmosphereColor = colorCorrect(atmosColor.mie) + finalColor.rgb * colorCorrect(atmosColor.rayleigh);
  413. #ifndef HDR
  414. groundAtmosphereColor = vec3(1.0) - exp(-fExposure * groundAtmosphereColor);
  415. #endif
  416. float fadeInDist = u_nightFadeDistance.x;
  417. float fadeOutDist = u_nightFadeDistance.y;
  418. float sunlitAtmosphereIntensity = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.0, 1.0);
  419. #ifdef HDR
  420. // Some tweaking to make HDR look better
  421. sunlitAtmosphereIntensity = max(sunlitAtmosphereIntensity * sunlitAtmosphereIntensity, 0.03);
  422. #endif
  423. groundAtmosphereColor = mix(groundAtmosphereColor, fogColor, sunlitAtmosphereIntensity);
  424. #else
  425. vec3 groundAtmosphereColor = fogColor;
  426. #endif
  427. #ifdef HDR
  428. // Some tweaking to make HDR look better
  429. groundAtmosphereColor = czm_saturation(groundAtmosphereColor, 1.6);
  430. #endif
  431. return groundAtmosphereColor;
  432. }
  433. #endif
  434. #ifdef SHOW_REFLECTIVE_OCEAN
  435. float waveFade(float edge0, float edge1, float x)
  436. {
  437. float y = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
  438. return pow(1.0 - y, 5.0);
  439. }
  440. float linearFade(float edge0, float edge1, float x)
  441. {
  442. return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
  443. }
  444. // Based on water rendering by Jonas Wagner:
  445. // http://29a.ch/2012/7/19/webgl-terrain-rendering-water-fog
  446. // low altitude wave settings
  447. const float oceanFrequencyLowAltitude = 825000.0;
  448. const float oceanAnimationSpeedLowAltitude = 0.004;
  449. const float oceanOneOverAmplitudeLowAltitude = 1.0 / 2.0;
  450. const float oceanSpecularIntensity = 0.5;
  451. // high altitude wave settings
  452. const float oceanFrequencyHighAltitude = 125000.0;
  453. const float oceanAnimationSpeedHighAltitude = 0.008;
  454. const float oceanOneOverAmplitudeHighAltitude = 1.0 / 2.0;
  455. vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float maskValue, float fade)
  456. {
  457. vec3 positionToEyeEC = -positionEyeCoordinates;
  458. float positionToEyeECLength = length(positionToEyeEC);
  459. // The double normalize below works around a bug in Firefox on Android devices.
  460. vec3 normalizedPositionToEyeEC = normalize(normalize(positionToEyeEC));
  461. // Fade out the waves as the camera moves far from the surface.
  462. float waveIntensity = waveFade(70000.0, 1000000.0, positionToEyeECLength);
  463. #ifdef SHOW_OCEAN_WAVES
  464. // high altitude waves
  465. float time = czm_frameNumber * oceanAnimationSpeedHighAltitude;
  466. vec4 noise = czm_getWaterNoise(u_oceanNormalMap, textureCoordinates * oceanFrequencyHighAltitude, time, 0.0);
  467. vec3 normalTangentSpaceHighAltitude = vec3(noise.xy, noise.z * oceanOneOverAmplitudeHighAltitude);
  468. // low altitude waves
  469. time = czm_frameNumber * oceanAnimationSpeedLowAltitude;
  470. noise = czm_getWaterNoise(u_oceanNormalMap, textureCoordinates * oceanFrequencyLowAltitude, time, 0.0);
  471. vec3 normalTangentSpaceLowAltitude = vec3(noise.xy, noise.z * oceanOneOverAmplitudeLowAltitude);
  472. // blend the 2 wave layers based on distance to surface
  473. float highAltitudeFade = linearFade(0.0, 60000.0, positionToEyeECLength);
  474. float lowAltitudeFade = 1.0 - linearFade(20000.0, 60000.0, positionToEyeECLength);
  475. vec3 normalTangentSpace =
  476. (highAltitudeFade * normalTangentSpaceHighAltitude) +
  477. (lowAltitudeFade * normalTangentSpaceLowAltitude);
  478. normalTangentSpace = normalize(normalTangentSpace);
  479. // fade out the normal perturbation as we move farther from the water surface
  480. normalTangentSpace.xy *= waveIntensity;
  481. normalTangentSpace = normalize(normalTangentSpace);
  482. #else
  483. vec3 normalTangentSpace = vec3(0.0, 0.0, 1.0);
  484. #endif
  485. vec3 normalEC = enuToEye * normalTangentSpace;
  486. const vec3 waveHighlightColor = vec3(0.3, 0.45, 0.6);
  487. // Use diffuse light to highlight the waves
  488. float diffuseIntensity = czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * maskValue;
  489. vec3 diffuseHighlight = waveHighlightColor * diffuseIntensity * (1.0 - fade);
  490. #ifdef SHOW_OCEAN_WAVES
  491. // Where diffuse light is low or non-existent, use wave highlights based solely on
  492. // the wave bumpiness and no particular light direction.
  493. float tsPerturbationRatio = normalTangentSpace.z;
  494. vec3 nonDiffuseHighlight = mix(waveHighlightColor * 5.0 * (1.0 - tsPerturbationRatio), vec3(0.0), diffuseIntensity);
  495. #else
  496. vec3 nonDiffuseHighlight = vec3(0.0);
  497. #endif
  498. // Add specular highlights in 3D, and in all modes when zoomed in.
  499. float specularIntensity = czm_getSpecular(czm_lightDirectionEC, normalizedPositionToEyeEC, normalEC, 10.0);
  500. float surfaceReflectance = mix(0.0, mix(u_zoomedOutOceanSpecularIntensity, oceanSpecularIntensity, waveIntensity), maskValue);
  501. float specular = specularIntensity * surfaceReflectance;
  502. #ifdef HDR
  503. specular *= 1.4;
  504. float e = 0.2;
  505. float d = 3.3;
  506. float c = 1.7;
  507. vec3 color = imageryColor.rgb + (c * (vec3(e) + imageryColor.rgb * d) * (diffuseHighlight + nonDiffuseHighlight + specular));
  508. #else
  509. vec3 color = imageryColor.rgb + diffuseHighlight + nonDiffuseHighlight + specular;
  510. #endif
  511. return vec4(color, imageryColor.a);
  512. }
  513. #endif // #ifdef SHOW_REFLECTIVE_OCEAN