SkyAtmosphere.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*global define*/
  2. define([
  3. '../Core/Cartesian3',
  4. '../Core/defaultValue',
  5. '../Core/defined',
  6. '../Core/defineProperties',
  7. '../Core/destroyObject',
  8. '../Core/Ellipsoid',
  9. '../Core/EllipsoidGeometry',
  10. '../Core/GeometryPipeline',
  11. '../Core/VertexFormat',
  12. '../Renderer/BufferUsage',
  13. '../Renderer/DrawCommand',
  14. '../Renderer/ShaderSource',
  15. '../Shaders/SkyAtmosphereFS',
  16. '../Shaders/SkyAtmosphereVS',
  17. './BlendingState',
  18. './CullFace',
  19. './SceneMode'
  20. ], function(
  21. Cartesian3,
  22. defaultValue,
  23. defined,
  24. defineProperties,
  25. destroyObject,
  26. Ellipsoid,
  27. EllipsoidGeometry,
  28. GeometryPipeline,
  29. VertexFormat,
  30. BufferUsage,
  31. DrawCommand,
  32. ShaderSource,
  33. SkyAtmosphereFS,
  34. SkyAtmosphereVS,
  35. BlendingState,
  36. CullFace,
  37. SceneMode) {
  38. "use strict";
  39. /**
  40. * An atmosphere drawn around the limb of the provided ellipsoid. Based on
  41. * {@link http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html|Accurate Atmospheric Scattering}
  42. * in GPU Gems 2.
  43. * <p>
  44. * This is only supported in 3D. atmosphere is faded out when morphing to 2D or Columbus view.
  45. * </p>
  46. *
  47. * @alias SkyAtmosphere
  48. * @constructor
  49. *
  50. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid that the atmosphere is drawn around.
  51. *
  52. * @example
  53. * scene.skyAtmosphere = new Cesium.SkyAtmosphere();
  54. *
  55. * @see Scene.skyAtmosphere
  56. */
  57. var SkyAtmosphere = function(ellipsoid) {
  58. ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
  59. /**
  60. * Determines if the atmosphere is shown.
  61. *
  62. * @type {Boolean}
  63. * @default true
  64. */
  65. this.show = true;
  66. this._ellipsoid = ellipsoid;
  67. this._command = new DrawCommand({
  68. owner : this
  69. });
  70. this._spSkyFromSpace = undefined;
  71. this._spSkyFromAtmosphere = undefined;
  72. this._fCameraHeight = undefined;
  73. this._fCameraHeight2 = undefined;
  74. this._outerRadius = Cartesian3.maximumComponent(Cartesian3.multiplyByScalar(ellipsoid.radii, 1.025, new Cartesian3()));
  75. var innerRadius = ellipsoid.maximumRadius;
  76. var rayleighScaleDepth = 0.25;
  77. var that = this;
  78. this._command.uniformMap = {
  79. fCameraHeight : function() {
  80. return that._fCameraHeight;
  81. },
  82. fCameraHeight2 : function() {
  83. return that._fCameraHeight2;
  84. },
  85. fOuterRadius : function() {
  86. return that._outerRadius;
  87. },
  88. fOuterRadius2 : function() {
  89. return that._outerRadius * that._outerRadius;
  90. },
  91. fInnerRadius : function() {
  92. return innerRadius;
  93. },
  94. fScale : function() {
  95. return 1.0 / (that._outerRadius - innerRadius);
  96. },
  97. fScaleDepth : function() {
  98. return rayleighScaleDepth;
  99. },
  100. fScaleOverScaleDepth : function() {
  101. return (1.0 / (that._outerRadius - innerRadius)) / rayleighScaleDepth;
  102. }
  103. };
  104. };
  105. defineProperties(SkyAtmosphere.prototype, {
  106. /**
  107. * Gets the ellipsoid the atmosphere is drawn around.
  108. * @memberof SkyAtmosphere.prototype
  109. *
  110. * @type {Ellipsoid}
  111. * @readonly
  112. */
  113. ellipsoid : {
  114. get : function() {
  115. return this._ellipsoid;
  116. }
  117. }
  118. });
  119. /**
  120. * @private
  121. */
  122. SkyAtmosphere.prototype.update = function(context, frameState) {
  123. if (!this.show) {
  124. return undefined;
  125. }
  126. if ((frameState.mode !== SceneMode.SCENE3D) &&
  127. (frameState.mode !== SceneMode.MORPHING)) {
  128. return undefined;
  129. }
  130. // The atmosphere is only rendered during the render pass; it is not pickable, it doesn't cast shadows, etc.
  131. if (!frameState.passes.render) {
  132. return undefined;
  133. }
  134. var command = this._command;
  135. if (!defined(command.vertexArray)) {
  136. var geometry = EllipsoidGeometry.createGeometry(new EllipsoidGeometry({
  137. radii : Cartesian3.multiplyByScalar(this._ellipsoid.radii, 1.025, new Cartesian3()),
  138. slicePartitions : 256,
  139. stackPartitions : 256,
  140. vertexFormat : VertexFormat.POSITION_ONLY
  141. }));
  142. command.vertexArray = context.createVertexArrayFromGeometry({
  143. geometry : geometry,
  144. attributeLocations : GeometryPipeline.createAttributeLocations(geometry),
  145. bufferUsage : BufferUsage.STATIC_DRAW
  146. });
  147. command.renderState = context.createRenderState({
  148. cull : {
  149. enabled : true,
  150. face : CullFace.FRONT
  151. },
  152. blending : BlendingState.ALPHA_BLEND
  153. });
  154. var vs = new ShaderSource({
  155. defines : ['SKY_FROM_SPACE'],
  156. sources : [SkyAtmosphereVS]
  157. });
  158. this._spSkyFromSpace = context.createShaderProgram(vs, SkyAtmosphereFS);
  159. vs = new ShaderSource({
  160. defines : ['SKY_FROM_ATMOSPHERE'],
  161. sources : [SkyAtmosphereVS]
  162. });
  163. this._spSkyFromAtmosphere = context.createShaderProgram(vs, SkyAtmosphereFS);
  164. }
  165. var cameraPosition = frameState.camera.positionWC;
  166. this._fCameraHeight2 = Cartesian3.magnitudeSquared(cameraPosition);
  167. this._fCameraHeight = Math.sqrt(this._fCameraHeight2);
  168. if (this._fCameraHeight > this._outerRadius) {
  169. // Camera in space
  170. command.shaderProgram = this._spSkyFromSpace;
  171. } else {
  172. // Camera in atmosphere
  173. command.shaderProgram = this._spSkyFromAtmosphere;
  174. }
  175. return command;
  176. };
  177. /**
  178. * Returns true if this object was destroyed; otherwise, false.
  179. * <br /><br />
  180. * If this object was destroyed, it should not be used; calling any function other than
  181. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  182. *
  183. * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  184. *
  185. * @see SkyAtmosphere#destroy
  186. */
  187. SkyAtmosphere.prototype.isDestroyed = function() {
  188. return false;
  189. };
  190. /**
  191. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  192. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  193. * <br /><br />
  194. * Once an object is destroyed, it should not be used; calling any function other than
  195. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  196. * assign the return value (<code>undefined</code>) to the object as done in the example.
  197. *
  198. * @returns {undefined}
  199. *
  200. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  201. *
  202. * @see SkyAtmosphere#isDestroyed
  203. *
  204. * @example
  205. * skyAtmosphere = skyAtmosphere && skyAtmosphere.destroy();
  206. */
  207. SkyAtmosphere.prototype.destroy = function() {
  208. var command = this._command;
  209. command.vertexArray = command.vertexArray && command.vertexArray.destroy();
  210. this._spSkyFromSpace = this._spSkyFromSpace && this._spSkyFromSpace.destroy();
  211. this._spSkyFromAtmosphere = this._spSkyFromAtmosphere && this._spSkyFromAtmosphere.destroy();
  212. return destroyObject(this);
  213. };
  214. return SkyAtmosphere;
  215. });