SkyBox.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import BoxGeometry from '../Core/BoxGeometry.js';
  2. import Cartesian3 from '../Core/Cartesian3.js';
  3. import defaultValue from '../Core/defaultValue.js';
  4. import defined from '../Core/defined.js';
  5. import destroyObject from '../Core/destroyObject.js';
  6. import DeveloperError from '../Core/DeveloperError.js';
  7. import GeometryPipeline from '../Core/GeometryPipeline.js';
  8. import Matrix4 from '../Core/Matrix4.js';
  9. import VertexFormat from '../Core/VertexFormat.js';
  10. import BufferUsage from '../Renderer/BufferUsage.js';
  11. import CubeMap from '../Renderer/CubeMap.js';
  12. import DrawCommand from '../Renderer/DrawCommand.js';
  13. import loadCubeMap from '../Renderer/loadCubeMap.js';
  14. import RenderState from '../Renderer/RenderState.js';
  15. import ShaderProgram from '../Renderer/ShaderProgram.js';
  16. import ShaderSource from '../Renderer/ShaderSource.js';
  17. import VertexArray from '../Renderer/VertexArray.js';
  18. import SkyBoxFS from '../Shaders/SkyBoxFS.js';
  19. import SkyBoxVS from '../Shaders/SkyBoxVS.js';
  20. import BlendingState from './BlendingState.js';
  21. import SceneMode from './SceneMode.js';
  22. /**
  23. * A sky box around the scene to draw stars. The sky box is defined using the True Equator Mean Equinox (TEME) axes.
  24. * <p>
  25. * This is only supported in 3D. The sky box is faded out when morphing to 2D or Columbus view. The size of
  26. * the sky box must not exceed {@link Scene#maximumCubeMapSize}.
  27. * </p>
  28. *
  29. * @alias SkyBox
  30. * @constructor
  31. *
  32. * @param {Object} options Object with the following properties:
  33. * @param {Object} [options.sources] The source URL or <code>Image</code> object for each of the six cube map faces. See the example below.
  34. * @param {Boolean} [options.show=true] Determines if this primitive will be shown.
  35. *
  36. *
  37. * @example
  38. * scene.skyBox = new Cesium.SkyBox({
  39. * sources : {
  40. * positiveX : 'skybox_px.png',
  41. * negativeX : 'skybox_nx.png',
  42. * positiveY : 'skybox_py.png',
  43. * negativeY : 'skybox_ny.png',
  44. * positiveZ : 'skybox_pz.png',
  45. * negativeZ : 'skybox_nz.png'
  46. * }
  47. * });
  48. *
  49. * @see Scene#skyBox
  50. * @see Transforms.computeTemeToPseudoFixedMatrix
  51. */
  52. function SkyBox(options) {
  53. /**
  54. * The sources used to create the cube map faces: an object
  55. * with <code>positiveX</code>, <code>negativeX</code>, <code>positiveY</code>,
  56. * <code>negativeY</code>, <code>positiveZ</code>, and <code>negativeZ</code> properties.
  57. * These can be either URLs or <code>Image</code> objects.
  58. *
  59. * @type Object
  60. * @default undefined
  61. */
  62. this.sources = options.sources;
  63. this._sources = undefined;
  64. /**
  65. * Determines if the sky box will be shown.
  66. *
  67. * @type {Boolean}
  68. * @default true
  69. */
  70. this.show = defaultValue(options.show, true);
  71. this._command = new DrawCommand({
  72. modelMatrix : Matrix4.clone(Matrix4.IDENTITY),
  73. owner : this
  74. });
  75. this._cubeMap = undefined;
  76. this._attributeLocations = undefined;
  77. this._useHdr = undefined;
  78. }
  79. /**
  80. * Called when {@link Viewer} or {@link CesiumWidget} render the scene to
  81. * get the draw commands needed to render this primitive.
  82. * <p>
  83. * Do not call this function directly. This is documented just to
  84. * list the exceptions that may be propagated when the scene is rendered:
  85. * </p>
  86. *
  87. * @exception {DeveloperError} this.sources is required and must have positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ properties.
  88. * @exception {DeveloperError} this.sources properties must all be the same type.
  89. */
  90. SkyBox.prototype.update = function(frameState, useHdr) {
  91. var that = this;
  92. if (!this.show) {
  93. return undefined;
  94. }
  95. if ((frameState.mode !== SceneMode.SCENE3D) &&
  96. (frameState.mode !== SceneMode.MORPHING)) {
  97. return undefined;
  98. }
  99. // The sky box is only rendered during the render pass; it is not pickable, it doesn't cast shadows, etc.
  100. if (!frameState.passes.render) {
  101. return undefined;
  102. }
  103. var context = frameState.context;
  104. if (this._sources !== this.sources) {
  105. this._sources = this.sources;
  106. var sources = this.sources;
  107. //>>includeStart('debug', pragmas.debug);
  108. if ((!defined(sources.positiveX)) ||
  109. (!defined(sources.negativeX)) ||
  110. (!defined(sources.positiveY)) ||
  111. (!defined(sources.negativeY)) ||
  112. (!defined(sources.positiveZ)) ||
  113. (!defined(sources.negativeZ))) {
  114. throw new DeveloperError('this.sources is required and must have positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ properties.');
  115. }
  116. if ((typeof sources.positiveX !== typeof sources.negativeX) ||
  117. (typeof sources.positiveX !== typeof sources.positiveY) ||
  118. (typeof sources.positiveX !== typeof sources.negativeY) ||
  119. (typeof sources.positiveX !== typeof sources.positiveZ) ||
  120. (typeof sources.positiveX !== typeof sources.negativeZ)) {
  121. throw new DeveloperError('this.sources properties must all be the same type.');
  122. }
  123. //>>includeEnd('debug');
  124. if (typeof sources.positiveX === 'string') {
  125. // Given urls for cube-map images. Load them.
  126. loadCubeMap(context, this._sources).then(function(cubeMap) {
  127. that._cubeMap = that._cubeMap && that._cubeMap.destroy();
  128. that._cubeMap = cubeMap;
  129. });
  130. } else {
  131. this._cubeMap = this._cubeMap && this._cubeMap.destroy();
  132. this._cubeMap = new CubeMap({
  133. context : context,
  134. source : sources
  135. });
  136. }
  137. }
  138. var command = this._command;
  139. if (!defined(command.vertexArray)) {
  140. command.uniformMap = {
  141. u_cubeMap: function() {
  142. return that._cubeMap;
  143. }
  144. };
  145. var geometry = BoxGeometry.createGeometry(BoxGeometry.fromDimensions({
  146. dimensions : new Cartesian3(2.0, 2.0, 2.0),
  147. vertexFormat : VertexFormat.POSITION_ONLY
  148. }));
  149. var attributeLocations = this._attributeLocations = GeometryPipeline.createAttributeLocations(geometry);
  150. command.vertexArray = VertexArray.fromGeometry({
  151. context : context,
  152. geometry : geometry,
  153. attributeLocations : attributeLocations,
  154. bufferUsage : BufferUsage.STATIC_DRAW
  155. });
  156. command.renderState = RenderState.fromCache({
  157. blending : BlendingState.ALPHA_BLEND
  158. });
  159. }
  160. if (!defined(command.shaderProgram) || this._useHdr !== useHdr) {
  161. var fs = new ShaderSource({
  162. defines : [useHdr ? 'HDR' : ''],
  163. sources : [SkyBoxFS]
  164. });
  165. command.shaderProgram = ShaderProgram.fromCache({
  166. context : context,
  167. vertexShaderSource : SkyBoxVS,
  168. fragmentShaderSource : fs,
  169. attributeLocations : this._attributeLocations
  170. });
  171. this._useHdr = useHdr;
  172. }
  173. if (!defined(this._cubeMap)) {
  174. return undefined;
  175. }
  176. return command;
  177. };
  178. /**
  179. * Returns true if this object was destroyed; otherwise, false.
  180. * <br /><br />
  181. * If this object was destroyed, it should not be used; calling any function other than
  182. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  183. *
  184. * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  185. *
  186. * @see SkyBox#destroy
  187. */
  188. SkyBox.prototype.isDestroyed = function() {
  189. return false;
  190. };
  191. /**
  192. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  193. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  194. * <br /><br />
  195. * Once an object is destroyed, it should not be used; calling any function other than
  196. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  197. * assign the return value (<code>undefined</code>) to the object as done in the example.
  198. *
  199. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  200. *
  201. *
  202. * @example
  203. * skyBox = skyBox && skyBox.destroy();
  204. *
  205. * @see SkyBox#isDestroyed
  206. */
  207. SkyBox.prototype.destroy = function() {
  208. var command = this._command;
  209. command.vertexArray = command.vertexArray && command.vertexArray.destroy();
  210. command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
  211. this._cubeMap = this._cubeMap && this._cubeMap.destroy();
  212. return destroyObject(this);
  213. };
  214. export default SkyBox;