Sun.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. import BoundingSphere from '../Core/BoundingSphere.js';
  2. import Cartesian2 from '../Core/Cartesian2.js';
  3. import Cartesian3 from '../Core/Cartesian3.js';
  4. import Cartesian4 from '../Core/Cartesian4.js';
  5. import ComponentDatatype from '../Core/ComponentDatatype.js';
  6. import defined from '../Core/defined.js';
  7. import defineProperties from '../Core/defineProperties.js';
  8. import destroyObject from '../Core/destroyObject.js';
  9. import IndexDatatype from '../Core/IndexDatatype.js';
  10. import CesiumMath from '../Core/Math.js';
  11. import Matrix4 from '../Core/Matrix4.js';
  12. import PixelFormat from '../Core/PixelFormat.js';
  13. import PrimitiveType from '../Core/PrimitiveType.js';
  14. import Buffer from '../Renderer/Buffer.js';
  15. import BufferUsage from '../Renderer/BufferUsage.js';
  16. import ComputeCommand from '../Renderer/ComputeCommand.js';
  17. import DrawCommand from '../Renderer/DrawCommand.js';
  18. import PixelDatatype from '../Renderer/PixelDatatype.js';
  19. import RenderState from '../Renderer/RenderState.js';
  20. import ShaderProgram from '../Renderer/ShaderProgram.js';
  21. import Texture from '../Renderer/Texture.js';
  22. import VertexArray from '../Renderer/VertexArray.js';
  23. import SunFS from '../Shaders/SunFS.js';
  24. import SunTextureFS from '../Shaders/SunTextureFS.js';
  25. import SunVS from '../Shaders/SunVS.js';
  26. import BlendingState from './BlendingState.js';
  27. import SceneMode from './SceneMode.js';
  28. import SceneTransforms from './SceneTransforms.js';
  29. /**
  30. * Draws a sun billboard.
  31. * <p>This is only supported in 3D and Columbus view.</p>
  32. *
  33. * @alias Sun
  34. * @constructor
  35. *
  36. *
  37. * @example
  38. * scene.sun = new Cesium.Sun();
  39. *
  40. * @see Scene#sun
  41. */
  42. function Sun() {
  43. /**
  44. * Determines if the sun will be shown.
  45. *
  46. * @type {Boolean}
  47. * @default true
  48. */
  49. this.show = true;
  50. this._drawCommand = new DrawCommand({
  51. primitiveType : PrimitiveType.TRIANGLES,
  52. boundingVolume : new BoundingSphere(),
  53. owner : this
  54. });
  55. this._commands = {
  56. drawCommand : this._drawCommand,
  57. computeCommand : undefined
  58. };
  59. this._boundingVolume = new BoundingSphere();
  60. this._boundingVolume2D = new BoundingSphere();
  61. this._texture = undefined;
  62. this._drawingBufferWidth = undefined;
  63. this._drawingBufferHeight = undefined;
  64. this._radiusTS = undefined;
  65. this._size = undefined;
  66. this.glowFactor = 1.0;
  67. this._glowFactorDirty = false;
  68. this._useHdr = undefined;
  69. var that = this;
  70. this._uniformMap = {
  71. u_texture : function() {
  72. return that._texture;
  73. },
  74. u_size : function() {
  75. return that._size;
  76. }
  77. };
  78. }
  79. defineProperties(Sun.prototype, {
  80. /**
  81. * Gets or sets a number that controls how "bright" the Sun's lens flare appears
  82. * to be. Zero shows just the Sun's disc without any flare.
  83. * Use larger values for a more pronounced flare around the Sun.
  84. *
  85. * @memberof Sun.prototype
  86. * @type {Number}
  87. * @default 1.0
  88. */
  89. glowFactor : {
  90. get : function () { return this._glowFactor; },
  91. set : function (glowFactor) {
  92. glowFactor = Math.max(glowFactor, 0.0);
  93. this._glowFactor = glowFactor;
  94. this._glowFactorDirty = true;
  95. }
  96. }
  97. });
  98. var scratchPositionWC = new Cartesian2();
  99. var scratchLimbWC = new Cartesian2();
  100. var scratchPositionEC = new Cartesian4();
  101. var scratchCartesian4 = new Cartesian4();
  102. /**
  103. * @private
  104. */
  105. Sun.prototype.update = function(frameState, passState, useHdr) {
  106. if (!this.show) {
  107. return undefined;
  108. }
  109. var mode = frameState.mode;
  110. if (mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) {
  111. return undefined;
  112. }
  113. if (!frameState.passes.render) {
  114. return undefined;
  115. }
  116. var context = frameState.context;
  117. var drawingBufferWidth = passState.viewport.width;
  118. var drawingBufferHeight = passState.viewport.height;
  119. if (!defined(this._texture) ||
  120. drawingBufferWidth !== this._drawingBufferWidth ||
  121. drawingBufferHeight !== this._drawingBufferHeight ||
  122. this._glowFactorDirty ||
  123. useHdr !== this._useHdr) {
  124. this._texture = this._texture && this._texture.destroy();
  125. this._drawingBufferWidth = drawingBufferWidth;
  126. this._drawingBufferHeight = drawingBufferHeight;
  127. this._glowFactorDirty = false;
  128. this._useHdr = useHdr;
  129. var size = Math.max(drawingBufferWidth, drawingBufferHeight);
  130. size = Math.pow(2.0, Math.ceil(Math.log(size) / Math.log(2.0)) - 2.0);
  131. // The size computed above can be less than 1.0 if size < 4.0. This will probably
  132. // never happen in practice, but does in the tests. Clamp to 1.0 to prevent WebGL
  133. // errors in the tests.
  134. size = Math.max(1.0, size);
  135. var pixelDatatype = useHdr ? (context.halfFloatingPointTexture ? PixelDatatype.HALF_FLOAT : PixelDatatype.FLOAT) : PixelDatatype.UNSIGNED_BYTE;
  136. this._texture = new Texture({
  137. context : context,
  138. width : size,
  139. height : size,
  140. pixelFormat : PixelFormat.RGBA,
  141. pixelDatatype : pixelDatatype
  142. });
  143. this._glowLengthTS = this._glowFactor * 5.0;
  144. this._radiusTS = (1.0 / (1.0 + 2.0 * this._glowLengthTS)) * 0.5;
  145. var that = this;
  146. var uniformMap = {
  147. u_radiusTS : function() {
  148. return that._radiusTS;
  149. }
  150. };
  151. this._commands.computeCommand = new ComputeCommand({
  152. fragmentShaderSource : SunTextureFS,
  153. outputTexture : this._texture,
  154. uniformMap : uniformMap,
  155. persists : false,
  156. owner : this,
  157. postExecute : function() {
  158. that._commands.computeCommand = undefined;
  159. }
  160. });
  161. }
  162. var drawCommand = this._drawCommand;
  163. if (!defined(drawCommand.vertexArray)) {
  164. var attributeLocations = {
  165. direction : 0
  166. };
  167. var directions = new Uint8Array(4 * 2);
  168. directions[0] = 0;
  169. directions[1] = 0;
  170. directions[2] = 255;
  171. directions[3] = 0.0;
  172. directions[4] = 255;
  173. directions[5] = 255;
  174. directions[6] = 0.0;
  175. directions[7] = 255;
  176. var vertexBuffer = Buffer.createVertexBuffer({
  177. context : context,
  178. typedArray : directions,
  179. usage : BufferUsage.STATIC_DRAW
  180. });
  181. var attributes = [{
  182. index : attributeLocations.direction,
  183. vertexBuffer : vertexBuffer,
  184. componentsPerAttribute : 2,
  185. normalize : true,
  186. componentDatatype : ComponentDatatype.UNSIGNED_BYTE
  187. }];
  188. // Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN
  189. var indexBuffer = Buffer.createIndexBuffer({
  190. context : context,
  191. typedArray : new Uint16Array([0, 1, 2, 0, 2, 3]),
  192. usage : BufferUsage.STATIC_DRAW,
  193. indexDatatype : IndexDatatype.UNSIGNED_SHORT
  194. });
  195. drawCommand.vertexArray = new VertexArray({
  196. context : context,
  197. attributes : attributes,
  198. indexBuffer : indexBuffer
  199. });
  200. drawCommand.shaderProgram = ShaderProgram.fromCache({
  201. context : context,
  202. vertexShaderSource : SunVS,
  203. fragmentShaderSource : SunFS,
  204. attributeLocations : attributeLocations
  205. });
  206. drawCommand.renderState = RenderState.fromCache({
  207. blending : BlendingState.ALPHA_BLEND
  208. });
  209. drawCommand.uniformMap = this._uniformMap;
  210. }
  211. var sunPosition = context.uniformState.sunPositionWC;
  212. var sunPositionCV = context.uniformState.sunPositionColumbusView;
  213. var boundingVolume = this._boundingVolume;
  214. var boundingVolume2D = this._boundingVolume2D;
  215. Cartesian3.clone(sunPosition, boundingVolume.center);
  216. boundingVolume2D.center.x = sunPositionCV.z;
  217. boundingVolume2D.center.y = sunPositionCV.x;
  218. boundingVolume2D.center.z = sunPositionCV.y;
  219. boundingVolume.radius = CesiumMath.SOLAR_RADIUS + CesiumMath.SOLAR_RADIUS * this._glowLengthTS;
  220. boundingVolume2D.radius = boundingVolume.radius;
  221. if (mode === SceneMode.SCENE3D) {
  222. BoundingSphere.clone(boundingVolume, drawCommand.boundingVolume);
  223. } else if (mode === SceneMode.COLUMBUS_VIEW) {
  224. BoundingSphere.clone(boundingVolume2D, drawCommand.boundingVolume);
  225. }
  226. var position = SceneTransforms.computeActualWgs84Position(frameState, sunPosition, scratchCartesian4);
  227. var dist = Cartesian3.magnitude(Cartesian3.subtract(position, frameState.camera.position, scratchCartesian4));
  228. var projMatrix = context.uniformState.projection;
  229. var positionEC = scratchPositionEC;
  230. positionEC.x = 0;
  231. positionEC.y = 0;
  232. positionEC.z = -dist;
  233. positionEC.w = 1;
  234. var positionCC = Matrix4.multiplyByVector(projMatrix, positionEC, scratchCartesian4);
  235. var positionWC = SceneTransforms.clipToGLWindowCoordinates(passState.viewport, positionCC, scratchPositionWC);
  236. positionEC.x = CesiumMath.SOLAR_RADIUS;
  237. var limbCC = Matrix4.multiplyByVector(projMatrix, positionEC, scratchCartesian4);
  238. var limbWC = SceneTransforms.clipToGLWindowCoordinates(passState.viewport, limbCC, scratchLimbWC);
  239. this._size = Cartesian2.magnitude(Cartesian2.subtract(limbWC, positionWC, scratchCartesian4));
  240. this._size = 2.0 * this._size * (1.0 + 2.0 * this._glowLengthTS);
  241. this._size = Math.ceil(this._size);
  242. return this._commands;
  243. };
  244. /**
  245. * Returns true if this object was destroyed; otherwise, false.
  246. * <br /><br />
  247. * If this object was destroyed, it should not be used; calling any function other than
  248. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  249. *
  250. * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  251. *
  252. * @see Sun#destroy
  253. */
  254. Sun.prototype.isDestroyed = function() {
  255. return false;
  256. };
  257. /**
  258. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  259. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  260. * <br /><br />
  261. * Once an object is destroyed, it should not be used; calling any function other than
  262. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  263. * assign the return value (<code>undefined</code>) to the object as done in the example.
  264. *
  265. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  266. *
  267. *
  268. * @example
  269. * sun = sun && sun.destroy();
  270. *
  271. * @see Sun#isDestroyed
  272. */
  273. Sun.prototype.destroy = function() {
  274. var command = this._drawCommand;
  275. command.vertexArray = command.vertexArray && command.vertexArray.destroy();
  276. command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
  277. this._texture = this._texture && this._texture.destroy();
  278. return destroyObject(this);
  279. };
  280. export default Sun;