cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
1,404 lines (1,279 loc) • 161 kB
JavaScript
import BoundingRectangle from '../Core/BoundingRectangle.js';
import BoundingSphere from '../Core/BoundingSphere.js';
import BoxGeometry from '../Core/BoxGeometry.js';
import Cartesian3 from '../Core/Cartesian3.js';
import Cartesian4 from '../Core/Cartesian4.js';
import Cartographic from '../Core/Cartographic.js';
import clone from '../Core/clone.js';
import Color from '../Core/Color.js';
import ColorGeometryInstanceAttribute from '../Core/ColorGeometryInstanceAttribute.js';
import createGuid from '../Core/createGuid.js';
import CullingVolume from '../Core/CullingVolume.js';
import defaultValue from '../Core/defaultValue.js';
import defined from '../Core/defined.js';
import deprecationWarning from '../Core/deprecationWarning.js';
import destroyObject from '../Core/destroyObject.js';
import DeveloperError from '../Core/DeveloperError.js';
import EllipsoidGeometry from '../Core/EllipsoidGeometry.js';
import Event from '../Core/Event.js';
import GeographicProjection from '../Core/GeographicProjection.js';
import GeometryInstance from '../Core/GeometryInstance.js';
import GeometryPipeline from '../Core/GeometryPipeline.js';
import Intersect from '../Core/Intersect.js';
import JulianDate from '../Core/JulianDate.js';
import CesiumMath from '../Core/Math.js';
import Matrix4 from '../Core/Matrix4.js';
import mergeSort from '../Core/mergeSort.js';
import Occluder from '../Core/Occluder.js';
import OrthographicFrustum from '../Core/OrthographicFrustum.js';
import OrthographicOffCenterFrustum from '../Core/OrthographicOffCenterFrustum.js';
import PerspectiveFrustum from '../Core/PerspectiveFrustum.js';
import PerspectiveOffCenterFrustum from '../Core/PerspectiveOffCenterFrustum.js';
import RequestScheduler from '../Core/RequestScheduler.js';
import TaskProcessor from '../Core/TaskProcessor.js';
import Transforms from '../Core/Transforms.js';
import ClearCommand from '../Renderer/ClearCommand.js';
import ComputeEngine from '../Renderer/ComputeEngine.js';
import Context from '../Renderer/Context.js';
import ContextLimits from '../Renderer/ContextLimits.js';
import DrawCommand from '../Renderer/DrawCommand.js';
import Pass from '../Renderer/Pass.js';
import RenderState from '../Renderer/RenderState.js';
import ShaderProgram from '../Renderer/ShaderProgram.js';
import ShaderSource from '../Renderer/ShaderSource.js';
import BrdfLutGenerator from './BrdfLutGenerator.js';
import Camera from './Camera.js';
import Cesium3DTilePass from './Cesium3DTilePass.js';
import Cesium3DTilePassState from './Cesium3DTilePassState.js';
import CreditDisplay from './CreditDisplay.js';
import DebugCameraPrimitive from './DebugCameraPrimitive.js';
import DepthPlane from './DepthPlane.js';
import DerivedCommand from './DerivedCommand.js';
import DeviceOrientationCameraController from './DeviceOrientationCameraController.js';
import Fog from './Fog.js';
import FrameState from './FrameState.js';
import GlobeDepth from './GlobeDepth.js';
import InvertClassification from './InvertClassification.js';
import JobScheduler from './JobScheduler.js';
import MapMode2D from './MapMode2D.js';
import OctahedralProjectedCubeMap from './OctahedralProjectedCubeMap.js';
import PerformanceDisplay from './PerformanceDisplay.js';
import PerInstanceColorAppearance from './PerInstanceColorAppearance.js';
import Picking from './Picking.js';
import PostProcessStageCollection from './PostProcessStageCollection.js';
import Primitive from './Primitive.js';
import PrimitiveCollection from './PrimitiveCollection.js';
import SceneMode from './SceneMode.js';
import SceneTransforms from './SceneTransforms.js';
import SceneTransitioner from './SceneTransitioner.js';
import ScreenSpaceCameraController from './ScreenSpaceCameraController.js';
import ShadowMap from './ShadowMap.js';
import StencilConstants from './StencilConstants.js';
import SunLight from './SunLight.js';
import SunPostProcess from './SunPostProcess.js';
import TweenCollection from './TweenCollection.js';
import View from './View.js';
var requestRenderAfterFrame = function (scene) {
return function () {
scene.frameState.afterRender.push(function() {
scene.requestRender();
});
};
};
/**
* The container for all 3D graphical objects and state in a Cesium virtual scene. Generally,
* a scene is not created directly; instead, it is implicitly created by {@link CesiumWidget}.
* <p>
* <em><code>contextOptions</code> parameter details:</em>
* </p>
* <p>
* The default values are:
* <code>
* {
* webgl : {
* alpha : false,
* depth : true,
* stencil : false,
* antialias : true,
* powerPreference: 'high-performance',
* premultipliedAlpha : true,
* preserveDrawingBuffer : false,
* failIfMajorPerformanceCaveat : false
* },
* allowTextureFilterAnisotropic : true
* }
* </code>
* </p>
* <p>
* The <code>webgl</code> property corresponds to the {@link http://www.khronos.org/registry/webgl/specs/latest/#5.2|WebGLContextAttributes}
* object used to create the WebGL context.
* </p>
* <p>
* <code>webgl.alpha</code> defaults to false, which can improve performance compared to the standard WebGL default
* of true. If an application needs to composite Cesium above other HTML elements using alpha-blending, set
* <code>webgl.alpha</code> to true.
* </p>
* <p>
* The other <code>webgl</code> properties match the WebGL defaults for {@link http://www.khronos.org/registry/webgl/specs/latest/#5.2|WebGLContextAttributes}.
* </p>
* <p>
* <code>allowTextureFilterAnisotropic</code> defaults to true, which enables anisotropic texture filtering when the
* WebGL extension is supported. Setting this to false will improve performance, but hurt visual quality, especially for horizon views.
* </p>
*
* @alias Scene
* @constructor
*
* @param {Object} [options] Object with the following properties:
* @param {Canvas} options.canvas The HTML canvas element to create the scene for.
* @param {Object} [options.contextOptions] Context and WebGL creation properties. See details above.
* @param {Element} [options.creditContainer] The HTML element in which the credits will be displayed.
* @param {Element} [options.creditViewport] The HTML element in which to display the credit popup. If not specified, the viewport will be a added as a sibling of the canvas.
* @param {MapProjection} [options.mapProjection=new GeographicProjection()] The map projection to use in 2D and Columbus View modes.
* @param {Boolean} [options.orderIndependentTranslucency=true] If true and the configuration supports it, use order independent translucency.
* @param {Boolean} [options.scene3DOnly=false] If true, optimizes memory use and performance for 3D mode but disables the ability to use 2D or Columbus View.
* @param {Number} [options.terrainExaggeration=1.0] A scalar used to exaggerate the terrain. Note that terrain exaggeration will not modify any other primitive as they are positioned relative to the ellipsoid.
* @param {Boolean} [options.shadows=false] Determines if shadows are cast by light sources.
* @param {MapMode2D} [options.mapMode2D=MapMode2D.INFINITE_SCROLL] Determines if the 2D map is rotatable or can be scrolled infinitely in the horizontal direction.
* @param {Boolean} [options.requestRenderMode=false] If true, rendering a frame will only occur when needed as determined by changes within the scene. Enabling improves performance of the application, but requires using {@link Scene#requestRender} to render a new frame explicitly in this mode. This will be necessary in many cases after making changes to the scene in other parts of the API. See {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}.
* @param {Number} [options.maximumRenderTimeChange=0.0] If requestRenderMode is true, this value defines the maximum change in simulation time allowed before a render is requested. See {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}.
*
* @see CesiumWidget
* @see {@link http://www.khronos.org/registry/webgl/specs/latest/#5.2|WebGLContextAttributes}
*
* @exception {DeveloperError} options and options.canvas are required.
*
* @example
* // Create scene without anisotropic texture filtering
* var scene = new Cesium.Scene({
* canvas : canvas,
* contextOptions : {
* allowTextureFilterAnisotropic : false
* }
* });
*/
function Scene(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
var canvas = options.canvas;
var creditContainer = options.creditContainer;
var creditViewport = options.creditViewport;
var contextOptions = clone(options.contextOptions);
if (!defined(contextOptions)) {
contextOptions = {};
}
if (!defined(contextOptions.webgl)) {
contextOptions.webgl = {};
}
contextOptions.webgl.powerPreference = defaultValue(contextOptions.webgl.powerPreference, 'high-performance');
//>>includeStart('debug', pragmas.debug);
if (!defined(canvas)) {
throw new DeveloperError('options and options.canvas are required.');
}
//>>includeEnd('debug');
var hasCreditContainer = defined(creditContainer);
var context = new Context(canvas, contextOptions);
if (!hasCreditContainer) {
creditContainer = document.createElement('div');
creditContainer.style.position = 'absolute';
creditContainer.style.bottom = '0';
creditContainer.style['text-shadow'] = '0 0 2px #000000';
creditContainer.style.color = '#ffffff';
creditContainer.style['font-size'] = '10px';
creditContainer.style['padding-right'] = '5px';
canvas.parentNode.appendChild(creditContainer);
}
if (!defined(creditViewport)) {
creditViewport = canvas.parentNode;
}
this._id = createGuid();
this._jobScheduler = new JobScheduler();
this._frameState = new FrameState(context, new CreditDisplay(creditContainer, ' • ', creditViewport), this._jobScheduler);
this._frameState.scene3DOnly = defaultValue(options.scene3DOnly, false);
this._removeCreditContainer = !hasCreditContainer;
this._creditContainer = creditContainer;
this._canvas = canvas;
this._context = context;
this._computeEngine = new ComputeEngine(context);
this._globe = undefined;
this._primitives = new PrimitiveCollection();
this._groundPrimitives = new PrimitiveCollection();
this._logDepthBuffer = context.fragmentDepth;
this._logDepthBufferDirty = true;
this._tweens = new TweenCollection();
this._shaderFrameCount = 0;
this._sunPostProcess = undefined;
this._computeCommandList = [];
this._overlayCommandList = [];
this._useOIT = defaultValue(options.orderIndependentTranslucency, true);
this._executeOITFunction = undefined;
this._depthPlane = new DepthPlane();
this._clearColorCommand = new ClearCommand({
color : new Color(),
stencil : 0,
owner : this
});
this._depthClearCommand = new ClearCommand({
depth : 1.0,
owner : this
});
this._stencilClearCommand = new ClearCommand({
stencil : 0
});
this._classificationStencilClearCommand = new ClearCommand({
stencil : 0,
renderState : RenderState.fromCache({
stencilMask : StencilConstants.CLASSIFICATION_MASK
})
});
this._depthOnlyRenderStateCache = {};
this._transitioner = new SceneTransitioner(this);
this._preUpdate = new Event();
this._postUpdate = new Event();
this._renderError = new Event();
this._preRender = new Event();
this._postRender = new Event();
this._minimumDisableDepthTestDistance = 0.0;
/**
* Exceptions occurring in <code>render</code> are always caught in order to raise the
* <code>renderError</code> event. If this property is true, the error is rethrown
* after the event is raised. If this property is false, the <code>render</code> function
* returns normally after raising the event.
*
* @type {Boolean}
* @default false
*/
this.rethrowRenderErrors = false;
/**
* Determines whether or not to instantly complete the
* scene transition animation on user input.
*
* @type {Boolean}
* @default true
*/
this.completeMorphOnUserInput = true;
/**
* The event fired at the beginning of a scene transition.
* @type {Event}
* @default Event()
*/
this.morphStart = new Event();
/**
* The event fired at the completion of a scene transition.
* @type {Event}
* @default Event()
*/
this.morphComplete = new Event();
/**
* The {@link SkyBox} used to draw the stars.
*
* @type {SkyBox}
* @default undefined
*
* @see Scene#backgroundColor
*/
this.skyBox = undefined;
/**
* The sky atmosphere drawn around the globe.
*
* @type {SkyAtmosphere}
* @default undefined
*/
this.skyAtmosphere = undefined;
/**
* The {@link Sun}.
*
* @type {Sun}
* @default undefined
*/
this.sun = undefined;
/**
* Uses a bloom filter on the sun when enabled.
*
* @type {Boolean}
* @default true
*/
this.sunBloom = true;
this._sunBloom = undefined;
/**
* The {@link Moon}
*
* @type Moon
* @default undefined
*/
this.moon = undefined;
/**
* The background color, which is only visible if there is no sky box, i.e., {@link Scene#skyBox} is undefined.
*
* @type {Color}
* @default {@link Color.BLACK}
*
* @see Scene#skyBox
*/
this.backgroundColor = Color.clone(Color.BLACK);
this._mode = SceneMode.SCENE3D;
this._mapProjection = defined(options.mapProjection) ? options.mapProjection : new GeographicProjection();
/**
* The current morph transition time between 2D/Columbus View and 3D,
* with 0.0 being 2D or Columbus View and 1.0 being 3D.
*
* @type {Number}
* @default 1.0
*/
this.morphTime = 1.0;
/**
* The far-to-near ratio of the multi-frustum when using a normal depth buffer.
* <p>
* This value is used to create the near and far values for each frustum of the multi-frustum. It is only used
* when {@link Scene#logarithmicDepthBuffer} is <code>false</code>. When <code>logarithmicDepthBuffer</code> is
* <code>true</code>, use {@link Scene#logarithmicDepthFarToNearRatio}.
* </p>
*
* @type {Number}
* @default 1000.0
*/
this.farToNearRatio = 1000.0;
/**
* The far-to-near ratio of the multi-frustum when using a logarithmic depth buffer.
* <p>
* This value is used to create the near and far values for each frustum of the multi-frustum. It is only used
* when {@link Scene#logarithmicDepthBuffer} is <code>true</code>. When <code>logarithmicDepthBuffer</code> is
* <code>false</code>, use {@link Scene#farToNearRatio}.
* </p>
*
* @type {Number}
* @default 1e9
*/
this.logarithmicDepthFarToNearRatio = 1e9;
/**
* Determines the uniform depth size in meters of each frustum of the multifrustum in 2D. If a primitive or model close
* to the surface shows z-fighting, decreasing this will eliminate the artifact, but decrease performance. On the
* other hand, increasing this will increase performance but may cause z-fighting among primitives close to the surface.
*
* @type {Number}
* @default 1.75e6
*/
this.nearToFarDistance2D = 1.75e6;
/**
* This property is for debugging only; it is not for production use.
* <p>
* A function that determines what commands are executed. As shown in the examples below,
* the function receives the command's <code>owner</code> as an argument, and returns a boolean indicating if the
* command should be executed.
* </p>
* <p>
* The default is <code>undefined</code>, indicating that all commands are executed.
* </p>
*
* @type Function
*
* @default undefined
*
* @example
* // Do not execute any commands.
* scene.debugCommandFilter = function(command) {
* return false;
* };
*
* // Execute only the billboard's commands. That is, only draw the billboard.
* var billboards = new Cesium.BillboardCollection();
* scene.debugCommandFilter = function(command) {
* return command.owner === billboards;
* };
*/
this.debugCommandFilter = undefined;
/**
* This property is for debugging only; it is not for production use.
* <p>
* When <code>true</code>, commands are randomly shaded. This is useful
* for performance analysis to see what parts of a scene or model are
* command-dense and could benefit from batching.
* </p>
*
* @type Boolean
*
* @default false
*/
this.debugShowCommands = false;
/**
* This property is for debugging only; it is not for production use.
* <p>
* When <code>true</code>, commands are shaded based on the frustums they
* overlap. Commands in the closest frustum are tinted red, commands in
* the next closest are green, and commands in the farthest frustum are
* blue. If a command overlaps more than one frustum, the color components
* are combined, e.g., a command overlapping the first two frustums is tinted
* yellow.
* </p>
*
* @type Boolean
*
* @default false
*/
this.debugShowFrustums = false;
/**
* This property is for debugging only; it is not for production use.
* <p>
* Displays frames per second and time between frames.
* </p>
*
* @type Boolean
*
* @default false
*/
this.debugShowFramesPerSecond = false;
/**
* This property is for debugging only; it is not for production use.
* <p>
* Displays depth information for the indicated frustum.
* </p>
*
* @type Boolean
*
* @default false
*/
this.debugShowGlobeDepth = false;
/**
* This property is for debugging only; it is not for production use.
* <p>
* Indicates which frustum will have depth information displayed.
* </p>
*
* @type Number
*
* @default 1
*/
this.debugShowDepthFrustum = 1;
/**
* This property is for debugging only; it is not for production use.
* <p>
* When <code>true</code>, draws outlines to show the boundaries of the camera frustums
* </p>
*
* @type Boolean
*
* @default false
*/
this.debugShowFrustumPlanes = false;
this._debugShowFrustumPlanes = false;
this._debugFrustumPlanes = undefined;
/**
* When <code>true</code>, enables picking using the depth buffer.
*
* @type Boolean
* @default true
*/
this.useDepthPicking = true;
/**
* When <code>true</code>, enables picking translucent geometry using the depth buffer. Note that {@link Scene#useDepthPicking} must also be true for enabling this to work.
*
* <p>
* Render must be called between picks.
* <br>There is a decrease in performance when enabled. There are extra draw calls to write depth for
* translucent geometry.
* </p>
*
* @example
* // picking the position of a translucent primitive
* viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
* var pickedFeature = viewer.scene.pick(movement.position);
* if (!Cesium.defined(pickedFeature)) {
* // nothing picked
* return;
* }
* viewer.scene.render();
* var worldPosition = viewer.scene.pickPosition(movement.position);
* }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
*
* @type {Boolean}
* @default false
*/
this.pickTranslucentDepth = false;
/**
* The time in milliseconds to wait before checking if the camera has not moved and fire the cameraMoveEnd event.
* @type {Number}
* @default 500.0
* @private
*/
this.cameraEventWaitTime = 500.0;
/**
* Blends the atmosphere to geometry far from the camera for horizon views. Allows for additional
* performance improvements by rendering less geometry and dispatching less terrain requests.
* @type {Fog}
*/
this.fog = new Fog();
this._shadowMapCamera = new Camera(this);
/**
* The shadow map for the scene's light source. When enabled, models, primitives, and the globe may cast and receive shadows.
* @type {ShadowMap}
*/
this.shadowMap = new ShadowMap({
context : context,
lightCamera : this._shadowMapCamera,
enabled : defaultValue(options.shadows, false)
});
/**
* When <code>false</code>, 3D Tiles will render normally. When <code>true</code>, classified 3D Tile geometry will render normally and
* unclassified 3D Tile geometry will render with the color multiplied by {@link Scene#invertClassificationColor}.
* @type {Boolean}
* @default false
*/
this.invertClassification = false;
/**
* The highlight color of unclassified 3D Tile geometry when {@link Scene#invertClassification} is <code>true</code>.
* <p>When the color's alpha is less than 1.0, the unclassified portions of the 3D Tiles will not blend correctly with the classified positions of the 3D Tiles.</p>
* <p>Also, when the color's alpha is less than 1.0, the WEBGL_depth_texture and EXT_frag_depth WebGL extensions must be supported.</p>
* @type {Color}
* @default Color.WHITE
*/
this.invertClassificationColor = Color.clone(Color.WHITE);
this._actualInvertClassificationColor = Color.clone(this._invertClassificationColor);
this._invertClassification = new InvertClassification();
/**
* The focal length for use when with cardboard or WebVR.
* @type {Number}
*/
this.focalLength = undefined;
/**
* The eye separation distance in meters for use with cardboard or WebVR.
* @type {Number}
*/
this.eyeSeparation = undefined;
/**
* Post processing effects applied to the final render.
* @type {PostProcessStageCollection}
*/
this.postProcessStages = new PostProcessStageCollection();
this._brdfLutGenerator = new BrdfLutGenerator();
this._terrainExaggeration = defaultValue(options.terrainExaggeration, 1.0);
this._performanceDisplay = undefined;
this._debugVolume = undefined;
this._screenSpaceCameraController = new ScreenSpaceCameraController(this);
this._mapMode2D = defaultValue(options.mapMode2D, MapMode2D.INFINITE_SCROLL);
// Keeps track of the state of a frame. FrameState is the state across
// the primitives of the scene. This state is for internally keeping track
// of celestial and environment effects that need to be updated/rendered in
// a certain order as well as updating/tracking framebuffer usage.
this._environmentState = {
skyBoxCommand : undefined,
skyAtmosphereCommand : undefined,
sunDrawCommand : undefined,
sunComputeCommand : undefined,
moonCommand : undefined,
isSunVisible : false,
isMoonVisible : false,
isReadyForAtmosphere : false,
isSkyAtmosphereVisible : false,
clearGlobeDepth : false,
useDepthPlane : false,
renderTranslucentDepthForPick : false,
originalFramebuffer : undefined,
useGlobeDepthFramebuffer : false,
separatePrimitiveFramebuffer : false,
useOIT : false,
useInvertClassification : false,
usePostProcess : false,
usePostProcessSelected : false,
useWebVR : false
};
this._useWebVR = false;
this._cameraVR = undefined;
this._aspectRatioVR = undefined;
/**
* When <code>true</code>, rendering a frame will only occur when needed as determined by changes within the scene.
* Enabling improves performance of the application, but requires using {@link Scene#requestRender}
* to render a new frame explicitly in this mode. This will be necessary in many cases after making changes
* to the scene in other parts of the API.
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#maximumRenderTimeChange
* @see Scene#requestRender
*
* @type {Boolean}
* @default false
*/
this.requestRenderMode = defaultValue(options.requestRenderMode, false);
this._renderRequested = true;
/**
* If {@link Scene#requestRenderMode} is <code>true</code>, this value defines the maximum change in
* simulation time allowed before a render is requested. Lower values increase the number of frames rendered
* and higher values decrease the number of frames rendered. If <code>undefined</code>, changes to
* the simulation time will never request a render.
* This value impacts the rate of rendering for changes in the scene like lighting, entity property updates,
* and animations.
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#requestRenderMode
*
* @type {Number}
* @default 0.5
*/
this.maximumRenderTimeChange = defaultValue(options.maximumRenderTimeChange, 0.0);
this._lastRenderTime = undefined;
this._frameRateMonitor = undefined;
this._removeRequestListenerCallback = RequestScheduler.requestCompletedEvent.addEventListener(requestRenderAfterFrame(this));
this._removeTaskProcessorListenerCallback = TaskProcessor.taskCompletedEvent.addEventListener(requestRenderAfterFrame(this));
this._removeGlobeCallbacks = [];
var viewport = new BoundingRectangle(0, 0, context.drawingBufferWidth, context.drawingBufferHeight);
var camera = new Camera(this);
if (this._logDepthBuffer) {
camera.frustum.near = 0.1;
camera.frustum.far = 10000000000.0;
}
/**
* The camera view for the scene camera flight destination. Used for preloading flight destination tiles.
* @type {Camera}
* @private
*/
this.preloadFlightCamera = new Camera(this);
/**
* The culling volume for the scene camera flight destination. Used for preloading flight destination tiles.
* @type {CullingVolume}
* @private
*/
this.preloadFlightCullingVolume = undefined;
this._picking = new Picking(this);
this._defaultView = new View(this, camera, viewport);
this._view = this._defaultView;
this._hdr = undefined;
this._hdrDirty = undefined;
this.highDynamicRange = false;
this.gamma = 2.2;
/**
* The spherical harmonic coefficients for image-based lighting of PBR models.
* @type {Cartesian3[]}
*/
this.sphericalHarmonicCoefficients = undefined;
/**
* The url to the KTX file containing the specular environment map and convoluted mipmaps for image-based lighting of PBR models.
* @type {String}
*/
this.specularEnvironmentMaps = undefined;
this._specularEnvironmentMapAtlas = undefined;
/**
* The light source for shading. Defaults to a directional light from the Sun.
* @type {Light}
*/
this.light = new SunLight();
// Give frameState, camera, and screen space camera controller initial state before rendering
updateFrameNumber(this, 0.0, JulianDate.now());
this.updateFrameState();
this.initializeFrame();
}
function updateGlobeListeners(scene, globe) {
for (var i = 0; i < scene._removeGlobeCallbacks.length; ++i) {
scene._removeGlobeCallbacks[i]();
}
scene._removeGlobeCallbacks.length = 0;
var removeGlobeCallbacks = [];
if (defined(globe)) {
removeGlobeCallbacks.push(globe.imageryLayersUpdatedEvent.addEventListener(requestRenderAfterFrame(scene)));
removeGlobeCallbacks.push(globe.terrainProviderChanged.addEventListener(requestRenderAfterFrame(scene)));
}
scene._removeGlobeCallbacks = removeGlobeCallbacks;
}
var scratchSunColor = new Cartesian4();
Object.defineProperties(Scene.prototype, {
/**
* Gets the canvas element to which this scene is bound.
* @memberof Scene.prototype
*
* @type {Canvas}
* @readonly
*/
canvas : {
get : function() {
return this._canvas;
}
},
/**
* The drawingBufferHeight of the underlying GL context.
* @memberof Scene.prototype
*
* @type {Number}
* @readonly
*
* @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight}
*/
drawingBufferHeight : {
get : function() {
return this._context.drawingBufferHeight;
}
},
/**
* The drawingBufferHeight of the underlying GL context.
* @memberof Scene.prototype
*
* @type {Number}
* @readonly
*
* @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight}
*/
drawingBufferWidth : {
get : function() {
return this._context.drawingBufferWidth;
}
},
/**
* The maximum aliased line width, in pixels, supported by this WebGL implementation. It will be at least one.
* @memberof Scene.prototype
*
* @type {Number}
* @readonly
*
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>ALIASED_LINE_WIDTH_RANGE</code>.
*/
maximumAliasedLineWidth : {
get : function() {
return ContextLimits.maximumAliasedLineWidth;
}
},
/**
* The maximum length in pixels of one edge of a cube map, supported by this WebGL implementation. It will be at least 16.
* @memberof Scene.prototype
*
* @type {Number}
* @readonly
*
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>GL_MAX_CUBE_MAP_TEXTURE_SIZE</code>.
*/
maximumCubeMapSize : {
get : function() {
return ContextLimits.maximumCubeMapSize;
}
},
/**
* Returns <code>true</code> if the {@link Scene#pickPosition} function is supported.
* @memberof Scene.prototype
*
* @type {Boolean}
* @readonly
*
* @see Scene#pickPosition
*/
pickPositionSupported : {
get : function() {
return this._context.depthTexture;
}
},
/**
* Returns <code>true</code> if the {@link Scene#sampleHeight} and {@link Scene#sampleHeightMostDetailed} functions are supported.
* @memberof Scene.prototype
*
* @type {Boolean}
* @readonly
*
* @see Scene#sampleHeight
* @see Scene#sampleHeightMostDetailed
*/
sampleHeightSupported : {
get : function() {
return this._context.depthTexture;
}
},
/**
* Returns <code>true</code> if the {@link Scene#clampToHeight} and {@link Scene#clampToHeightMostDetailed} functions are supported.
* @memberof Scene.prototype
*
* @type {Boolean}
* @readonly
*
* @see Scene#clampToHeight
* @see Scene#clampToHeightMostDetailed
*/
clampToHeightSupported : {
get : function() {
return this._context.depthTexture;
}
},
/**
* Returns <code>true</code> if the {@link Scene#invertClassification} is supported.
* @memberof Scene.prototype
*
* @type {Boolean}
* @readonly
*
* @see Scene#invertClassification
*/
invertClassificationSupported : {
get : function() {
return this._context.depthTexture;
}
},
/**
* Returns <code>true</code> if specular environment maps are supported.
* @memberof Scene.prototype
*
* @type {Boolean}
* @readonly
*
* @see Scene#specularEnvironmentMaps
*/
specularEnvironmentMapsSupported : {
get : function() {
return OctahedralProjectedCubeMap.isSupported(this._context);
}
},
/**
* Gets or sets the depth-test ellipsoid.
* @memberof Scene.prototype
*
* @type {Globe}
*/
globe : {
get: function() {
return this._globe;
},
set: function(globe) {
this._globe = this._globe && this._globe.destroy();
this._globe = globe;
updateGlobeListeners(this, globe);
}
},
/**
* Gets the collection of primitives.
* @memberof Scene.prototype
*
* @type {PrimitiveCollection}
* @readonly
*/
primitives : {
get : function() {
return this._primitives;
}
},
/**
* Gets the collection of ground primitives.
* @memberof Scene.prototype
*
* @type {PrimitiveCollection}
* @readonly
*/
groundPrimitives : {
get : function() {
return this._groundPrimitives;
}
},
/**
* Gets or sets the camera.
* @memberof Scene.prototype
*
* @type {Camera}
* @readonly
*/
camera : {
get : function() {
return this._view.camera;
},
set : function(camera) {
// For internal use only. Documentation is still @readonly.
this._view.camera = camera;
}
},
/**
* Gets or sets the view.
* @memberof Scene.prototype
*
* @type {View}
* @readonly
*
* @private
*/
view : {
get : function() {
return this._view;
},
set : function(view) {
// For internal use only. Documentation is still @readonly.
this._view = view;
}
},
/**
* Gets the default view.
* @memberof Scene.prototype
*
* @type {View}
* @readonly
*
* @private
*/
defaultView : {
get : function() {
return this._defaultView;
}
},
/**
* Gets picking functions and state
* @memberof Scene.prototype
*
* @type {Picking}
* @readonly
*
* @private
*/
picking : {
get : function() {
return this._picking;
}
},
/**
* Gets the controller for camera input handling.
* @memberof Scene.prototype
*
* @type {ScreenSpaceCameraController}
* @readonly
*/
screenSpaceCameraController : {
get : function() {
return this._screenSpaceCameraController;
}
},
/**
* Get the map projection to use in 2D and Columbus View modes.
* @memberof Scene.prototype
*
* @type {MapProjection}
* @readonly
*
* @default new GeographicProjection()
*/
mapProjection : {
get: function() {
return this._mapProjection;
}
},
/**
* Gets the job scheduler
* @memberof Scene.prototype
* @type {JobScheduler}
* @readonly
*
* @private
*/
jobScheduler : {
get: function() {
return this._jobScheduler;
}
},
/**
* Gets state information about the current scene. If called outside of a primitive's <code>update</code>
* function, the previous frame's state is returned.
* @memberof Scene.prototype
*
* @type {FrameState}
* @readonly
*
* @private
*/
frameState : {
get: function() {
return this._frameState;
}
},
/**
* Gets the environment state.
* @memberof Scene.prototype
*
* @type {EnvironmentState}
* @readonly
*
* @private
*/
environmentState : {
get: function() {
return this._environmentState;
}
},
/**
* Gets the collection of tweens taking place in the scene.
* @memberof Scene.prototype
*
* @type {TweenCollection}
* @readonly
*
* @private
*/
tweens : {
get : function() {
return this._tweens;
}
},
/**
* Gets the collection of image layers that will be rendered on the globe.
* @memberof Scene.prototype
*
* @type {ImageryLayerCollection}
* @readonly
*/
imageryLayers : {
get : function() {
if (!defined(this.globe)) {
return undefined;
}
return this.globe.imageryLayers;
}
},
/**
* The terrain provider providing surface geometry for the globe.
* @memberof Scene.prototype
*
* @type {TerrainProvider}
*/
terrainProvider : {
get : function() {
if (!defined(this.globe)) {
return undefined;
}
return this.globe.terrainProvider;
},
set : function(terrainProvider) {
if (defined(this.globe)) {
this.globe.terrainProvider = terrainProvider;
}
}
},
/**
* Gets an event that's raised when the terrain provider is changed
* @memberof Scene.prototype
*
* @type {Event}
* @readonly
*/
terrainProviderChanged : {
get : function() {
if (!defined(this.globe)) {
return undefined;
}
return this.globe.terrainProviderChanged;
}
},
/**
* Gets the event that will be raised before the scene is updated or rendered. Subscribers to the event
* receive the Scene instance as the first parameter and the current time as the second parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#postUpdate
* @see Scene#preRender
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
preUpdate : {
get : function() {
return this._preUpdate;
}
},
/**
* Gets the event that will be raised immediately after the scene is updated and before the scene is rendered.
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
* parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#preUpdate
* @see Scene#preRender
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
postUpdate : {
get : function() {
return this._postUpdate;
}
},
/**
* Gets the event that will be raised when an error is thrown inside the <code>render</code> function.
* The Scene instance and the thrown error are the only two parameters passed to the event handler.
* By default, errors are not rethrown after this event is raised, but that can be changed by setting
* the <code>rethrowRenderErrors</code> property.
* @memberof Scene.prototype
*
* @type {Event}
* @readonly
*/
renderError : {
get : function() {
return this._renderError;
}
},
/**
* Gets the event that will be raised after the scene is updated and immediately before the scene is rendered.
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
* parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#preUpdate
* @see Scene#postUpdate
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
preRender : {
get : function() {
return this._preRender;
}
},
/**
* Gets the event that will be raised immediately after the scene is rendered. Subscribers to the event
* receive the Scene instance as the first parameter and the current time as the second parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#preUpdate
* @see Scene#postUpdate
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
postRender : {
get : function() {
return this._postRender;
}
},
/**
* Gets the simulation time when the scene was last rendered. Returns undefined if the scene has not yet been
* rendered.
* @memberof Scene.prototype
*
* @type {JulianDate}
* @readonly
*/
lastRenderTime : {
get : function() {
return this._lastRenderTime;
}
},
/**
* @memberof Scene.prototype
* @private
* @readonly
*/
context : {
get : function() {
return this._context;
}
},
/**
* This property is for debugging only; it is not for production use.
* <p>
* When {@link Scene.debugShowFrustums} is <code>true</code>, this contains
* properties with statistics about the number of command execute per frustum.
* <code>totalCommands</code> is the total number of commands executed, ignoring
* overlap. <code>commandsInFrustums</code> is an array with the number of times
* commands are executed redundantly, e.g., how many commands overlap two or
* three frustums.
* </p>
*
* @memberof Scene.prototype
*
* @type {Object}
* @readonly
*
* @default undefined
*/
debugFrustumStatistics : {
get : function() {
return this._view.debugFrustumStatistics;
}
},
/**
* Gets whether or not the scene is optimized for 3D only viewing.
* @memberof Scene.prototype
* @type {Boolean}
* @readonly
*/
scene3DOnly : {
get : function() {
return this._frameState.scene3DOnly;
}
},
/**
* Gets whether or not the scene has order independent translucency enabled.
* Note that this only reflects the original construction option, and there are
* other factors that could prevent OIT from functioning on a given system configuration.
* @memberof Scene.prototype
* @type {Boolean}
* @readonly
*/
orderIndependentTranslucency : {
get : function() {
return this._useOIT;
}
},
/**
* Gets the unique identifier for this scene.
* @memberof Scene.prototype
* @type {String}
* @readonly
*/
id : {
get : function() {
return this._id;
}
},
/**
* Gets or sets the current mode of the scene.
* @memberof Scene.prototype
* @type {SceneMode}
* @default {@link SceneMode.SCENE3D}
*/
mode : {
get : function() {
return this._mode;
},
set : function(value) {
//>>includeStart('debug', pragmas.debug);
if (this.scene3DOnly && value !== SceneMode.SCENE3D) {
throw new DeveloperError('Only SceneMode.SCENE3D is valid when scene3DOnly is true.');
}
//>>includeEnd('debug');
if (value === SceneMode.SCENE2D) {
this.morphTo2D(0);
} else if (value === SceneMode.SCENE3D) {
this.morphTo3D(0);
} else if (value === SceneMode.COLUMBUS_VIEW) {
this.morphToColumbusView(0);
//>>includeStart('debug', pragmas.debug);
} else {
throw new DeveloperError('value must be a valid SceneMode enumeration.');
//>>includeEnd('debug');
}
this._mode = value;
}
},
/**
* Gets the number of frustums used in the last frame.
* @memberof Scene.prototype
* @type {FrustumCommands[]}
*
* @private
*/
frustumCommandsList : {
get : function() {
return this._view.frustumCommandsList;
}
},
/**
* Gets the number of frustums used in the last frame.
* @memberof Scene.prototype
* @type {Number}
*
* @private
*/
numberOfFrustums : {
get : function() {
return this._view.frustumCommandsList.length;
}
},
/**
* Gets the scalar used to exaggerate the terrain.
* @memberof Scene.prototype
* @type {Number}
*/
terrainExaggeration : {
get : function()