LensFlare.glsl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. uniform sampler2D colorTexture;
  2. uniform sampler2D dirtTexture;
  3. uniform sampler2D starTexture;
  4. uniform vec2 dirtTextureDimensions;
  5. uniform float distortion;
  6. uniform float ghostDispersal;
  7. uniform float haloWidth;
  8. uniform float dirtAmount;
  9. uniform float earthRadius;
  10. uniform float intensity;
  11. varying vec2 v_textureCoordinates;
  12. // whether it is in space or not
  13. // 6500000.0 is empirical value
  14. #define DISTANCE_TO_SPACE 6500000.0
  15. // return ndc from world coordinate biased earthRadius
  16. vec4 getNDCFromWC(vec3 WC, float earthRadius)
  17. {
  18. vec4 positionEC = czm_view * vec4(WC, 1.0);
  19. positionEC = vec4(positionEC.x + earthRadius, positionEC.y, positionEC.z, 1.0);
  20. vec4 positionWC = czm_eyeToWindowCoordinates(positionEC);
  21. return czm_viewportOrthographic * vec4(positionWC.xy, -positionWC.z, 1.0);
  22. }
  23. // Check if current pixel is included Earth
  24. // if then mask it gradually
  25. float isInEarth(vec2 texcoord, vec2 sceneSize)
  26. {
  27. vec2 NDC = texcoord * 2.0 - 1.0;
  28. vec4 earthPosSC = getNDCFromWC(vec3(0.0), 0.0);
  29. vec4 earthPosSCEdge = getNDCFromWC(vec3(0.0), earthRadius * 1.5);
  30. NDC.xy -= earthPosSC.xy;
  31. float X = abs(NDC.x) * sceneSize.x;
  32. float Y = abs(NDC.y) * sceneSize.y;
  33. return clamp(0.0, 1.0, max(sqrt(X * X + Y * Y) / max(abs(earthPosSCEdge.x * sceneSize.x), 1.0) - 0.8 , 0.0));
  34. }
  35. // For Chromatic effect
  36. vec4 textureDistorted(sampler2D tex, vec2 texcoord, vec2 direction, vec3 distortion, bool isSpace)
  37. {
  38. vec2 sceneSize = czm_viewport.zw;
  39. vec3 color;
  40. if(isSpace)
  41. {
  42. color.r = isInEarth(texcoord + direction * distortion.r, sceneSize) * texture2D(tex, texcoord + direction * distortion.r).r;
  43. color.g = isInEarth(texcoord + direction * distortion.g, sceneSize) * texture2D(tex, texcoord + direction * distortion.g).g;
  44. color.b = isInEarth(texcoord + direction * distortion.b, sceneSize) * texture2D(tex, texcoord + direction * distortion.b).b;
  45. }
  46. else
  47. {
  48. color.r = texture2D(tex, texcoord + direction * distortion.r).r;
  49. color.g = texture2D(tex, texcoord + direction * distortion.g).g;
  50. color.b = texture2D(tex, texcoord + direction * distortion.b).b;
  51. }
  52. return vec4(clamp(color, 0.0, 1.0), 0.0);
  53. }
  54. void main(void)
  55. {
  56. vec4 originalColor = texture2D(colorTexture, v_textureCoordinates);
  57. vec3 rgb = originalColor.rgb;
  58. bool isSpace = length(czm_viewerPositionWC.xyz) > DISTANCE_TO_SPACE;
  59. // Sun position
  60. vec4 sunPos = czm_morphTime == 1.0 ? vec4(czm_sunPositionWC, 1.0) : vec4(czm_sunPositionColumbusView.zxy, 1.0);
  61. vec4 sunPositionEC = czm_view * sunPos;
  62. vec4 sunPositionWC = czm_eyeToWindowCoordinates(sunPositionEC);
  63. sunPos = czm_viewportOrthographic * vec4(sunPositionWC.xy, -sunPositionWC.z, 1.0);
  64. // If sun is not in the screen space, use original color.
  65. if(!isSpace || !((sunPos.x >= -1.1 && sunPos.x <= 1.1) && (sunPos.y >= -1.1 && sunPos.y <= 1.1)))
  66. {
  67. // Lens flare is disabled when not in space until #5932 is fixed.
  68. // https://github.com/AnalyticalGraphicsInc/cesium/issues/5932
  69. gl_FragColor = originalColor;
  70. return;
  71. }
  72. vec2 texcoord = vec2(1.0) - v_textureCoordinates;
  73. vec2 pixelSize = czm_pixelRatio / czm_viewport.zw;
  74. vec2 invPixelSize = 1.0 / pixelSize;
  75. vec3 distortionVec = pixelSize.x * vec3(-distortion, 0.0, distortion);
  76. // ghost vector to image centre:
  77. vec2 ghostVec = (vec2(0.5) - texcoord) * ghostDispersal;
  78. vec3 direction = normalize(vec3(ghostVec, 0.0));
  79. // sample ghosts:
  80. vec4 result = vec4(0.0);
  81. vec4 ghost = vec4(0.0);
  82. for (int i = 0; i < 4; ++i)
  83. {
  84. vec2 offset = fract(texcoord + ghostVec * float(i));
  85. // Only bright spots from the centre of the source image
  86. ghost += textureDistorted(colorTexture, offset, direction.xy, distortionVec, isSpace);
  87. }
  88. result += ghost;
  89. // sample halo
  90. vec2 haloVec = normalize(ghostVec) * haloWidth;
  91. float weightForHalo = length(vec2(0.5) - fract(texcoord + haloVec)) / length(vec2(0.5));
  92. weightForHalo = pow(1.0 - weightForHalo, 5.0);
  93. result += textureDistorted(colorTexture, texcoord + haloVec, direction.xy, distortionVec, isSpace) * weightForHalo * 1.5;
  94. // dirt on lens
  95. vec2 dirtTexCoords = (v_textureCoordinates * invPixelSize) / dirtTextureDimensions;
  96. if (dirtTexCoords.x > 1.0)
  97. {
  98. dirtTexCoords.x = mod(floor(dirtTexCoords.x), 2.0) == 1.0 ? 1.0 - fract(dirtTexCoords.x) : fract(dirtTexCoords.x);
  99. }
  100. if (dirtTexCoords.y > 1.0)
  101. {
  102. dirtTexCoords.y = mod(floor(dirtTexCoords.y), 2.0) == 1.0 ? 1.0 - fract(dirtTexCoords.y) : fract(dirtTexCoords.y);
  103. }
  104. result += dirtAmount * texture2D(dirtTexture, dirtTexCoords);
  105. // Rotating starburst texture's coordinate
  106. // dot(czm_view[0].xyz, vec3(0.0, 0.0, 1.0)) + dot(czm_view[1].xyz, vec3(0.0, 1.0, 0.0))
  107. float camrot = czm_view[0].z + czm_view[1].y;
  108. float cosValue = cos(camrot);
  109. float sinValue = sin(camrot);
  110. mat3 rotation = mat3(
  111. cosValue, -sinValue, 0.0,
  112. sinValue, cosValue, 0.0,
  113. 0.0, 0.0, 1.0
  114. );
  115. vec3 st1 = vec3(v_textureCoordinates * 2.0 - vec2(1.0), 1.0);
  116. vec3 st2 = vec3((rotation * st1).xy, 1.0);
  117. vec3 st3 = st2 * 0.5 + vec3(0.5);
  118. vec2 lensStarTexcoord = st3.xy;
  119. float weightForLensFlare = length(vec3(sunPos.xy, 0.0));
  120. float oneMinusWeightForLensFlare = max(1.0 - weightForLensFlare, 0.0);
  121. if (!isSpace)
  122. {
  123. result *= oneMinusWeightForLensFlare * intensity * 0.2;
  124. }
  125. else
  126. {
  127. result *= oneMinusWeightForLensFlare * intensity;
  128. result *= texture2D(starTexture, lensStarTexcoord) * pow(weightForLensFlare, 1.0) * max((1.0 - length(vec3(st1.xy, 0.0))), 0.0) * 2.0;
  129. }
  130. result += texture2D(colorTexture, v_textureCoordinates);
  131. gl_FragColor = result;
  132. }