SkyAtmosphereCommon.glsl 4.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. float interpolateByDistance(vec4 nearFarScalar, float distance)
  2. {
  3. float startDistance = nearFarScalar.x;
  4. float startValue = nearFarScalar.y;
  5. float endDistance = nearFarScalar.z;
  6. float endValue = nearFarScalar.w;
  7. float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0);
  8. return mix(startValue, endValue, t);
  9. }
  10. vec3 getLightDirection(vec3 positionWC)
  11. {
  12. float lightEnum = u_radiiAndDynamicAtmosphereColor.z;
  13. vec3 lightDirection =
  14. positionWC * float(lightEnum == 0.0) +
  15. czm_lightDirectionWC * float(lightEnum == 1.0) +
  16. czm_sunDirectionWC * float(lightEnum == 2.0);
  17. return normalize(lightDirection);
  18. }
  19. void computeAtmosphereScattering(vec3 positionWC, vec3 lightDirection, out vec3 rayleighColor, out vec3 mieColor, out float opacity, out float underTranslucentGlobe)
  20. {
  21. float ellipsoidRadiiDifference = czm_ellipsoidRadii.x - czm_ellipsoidRadii.z;
  22. // Adjustment to the atmosphere radius applied based on the camera height.
  23. float distanceAdjustMin = czm_ellipsoidRadii.x / 4.0;
  24. float distanceAdjustMax = czm_ellipsoidRadii.x;
  25. float distanceAdjustModifier = ellipsoidRadiiDifference / 2.0;
  26. float distanceAdjust = distanceAdjustModifier * clamp((czm_eyeHeight - distanceAdjustMin) / (distanceAdjustMax - distanceAdjustMin), 0.0, 1.0);
  27. // Since atmosphere scattering assumes the atmosphere is a spherical shell, we compute an inner radius of the atmosphere best fit
  28. // for the position on the ellipsoid.
  29. float radiusAdjust = (ellipsoidRadiiDifference / 4.0) + distanceAdjust;
  30. float atmosphereInnerRadius = (length(czm_viewerPositionWC) - czm_eyeHeight) - radiusAdjust;
  31. // Setup the primary ray: from the camera position to the vertex position.
  32. vec3 cameraToPositionWC = positionWC - czm_viewerPositionWC;
  33. vec3 cameraToPositionWCDirection = normalize(cameraToPositionWC);
  34. czm_ray primaryRay = czm_ray(czm_viewerPositionWC, cameraToPositionWCDirection);
  35. underTranslucentGlobe = 0.0;
  36. // Brighten the sky atmosphere under the Earth's atmosphere when translucency is enabled.
  37. #if defined(GLOBE_TRANSLUCENT)
  38. // Check for intersection with the inner radius of the atmopshere.
  39. czm_raySegment primaryRayEarthIntersect = czm_raySphereIntersectionInterval(primaryRay, vec3(0.0), atmosphereInnerRadius + radiusAdjust);
  40. if (primaryRayEarthIntersect.start > 0.0 && primaryRayEarthIntersect.stop > 0.0) {
  41. // Compute position on globe.
  42. vec3 direction = normalize(positionWC);
  43. czm_ray ellipsoidRay = czm_ray(positionWC, -direction);
  44. czm_raySegment ellipsoidIntersection = czm_rayEllipsoidIntersectionInterval(ellipsoidRay, vec3(0.0), czm_ellipsoidInverseRadii);
  45. vec3 onEarth = positionWC - (direction * ellipsoidIntersection.start);
  46. // Control the color using the camera angle.
  47. float angle = dot(normalize(czm_viewerPositionWC), normalize(onEarth));
  48. // Control the opacity using the distance from Earth.
  49. opacity = interpolateByDistance(vec4(0.0, 1.0, czm_ellipsoidRadii.x, 0.0), length(czm_viewerPositionWC - onEarth));
  50. vec3 horizonColor = vec3(0.1, 0.2, 0.3);
  51. vec3 nearColor = vec3(0.0);
  52. rayleighColor = mix(nearColor, horizonColor, exp(-angle) * opacity);
  53. // Set the traslucent flag to avoid alpha adjustment in computeFinalColor funciton.
  54. underTranslucentGlobe = 1.0;
  55. return;
  56. }
  57. #endif
  58. computeScattering(
  59. primaryRay,
  60. length(cameraToPositionWC),
  61. lightDirection,
  62. atmosphereInnerRadius,
  63. rayleighColor,
  64. mieColor,
  65. opacity
  66. );
  67. // Alter the opacity based on how close the viewer is to the ground.
  68. // (0.0 = At edge of atmosphere, 1.0 = On ground)
  69. float cameraHeight = czm_eyeHeight + atmosphereInnerRadius;
  70. float atmosphereOuterRadius = atmosphereInnerRadius + ATMOSPHERE_THICKNESS;
  71. opacity = clamp((atmosphereOuterRadius - cameraHeight) / (atmosphereOuterRadius - atmosphereInnerRadius), 0.0, 1.0);
  72. // Alter alpha based on time of day (0.0 = night , 1.0 = day)
  73. float nightAlpha = (u_radiiAndDynamicAtmosphereColor.z != 0.0) ? clamp(dot(normalize(positionWC), lightDirection), 0.0, 1.0) : 1.0;
  74. opacity *= pow(nightAlpha, 0.5);
  75. }