diff --git a/Source/Core/ApproximateTerrainHeights.js b/Source/Core/ApproximateTerrainHeights.js
index 39fabe916bab..0072ae79e55c 100644
--- a/Source/Core/ApproximateTerrainHeights.js
+++ b/Source/Core/ApproximateTerrainHeights.js
@@ -68,7 +68,7 @@ define([
/**
* Computes the minimum and maximum terrain heights for a given rectangle
- * @param {Rectangle} rectangle THe bounding rectangle
+ * @param {Rectangle} rectangle The bounding rectangle
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid
* @return {{minimumTerrainHeight: Number, maximumTerrainHeight: Number}}
*/
diff --git a/Source/Core/IonGeocoderService.js b/Source/Core/IonGeocoderService.js
index c00cc988651b..e0c2919ac029 100644
--- a/Source/Core/IonGeocoderService.js
+++ b/Source/Core/IonGeocoderService.js
@@ -44,7 +44,7 @@ define([
var defaultTokenCredit = Ion.getDefaultTokenCredit(accessToken);
if (defined(defaultTokenCredit)) {
- options.scene._frameState.creditDisplay.addDefaultCredit(defaultTokenCredit);
+ options.scene.frameState.creditDisplay.addDefaultCredit(defaultTokenCredit);
}
var searchEndpoint = server.getDerivedResource({
diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js
index 575098f04cd8..96c844af672e 100644
--- a/Source/Renderer/Context.js
+++ b/Source/Renderer/Context.js
@@ -23,7 +23,6 @@ define([
'./CubeMap',
'./DrawCommand',
'./PassState',
- './PickFramebuffer',
'./PixelDatatype',
'./RenderState',
'./ShaderCache',
@@ -56,7 +55,6 @@ define([
CubeMap,
DrawCommand,
PassState,
- PickFramebuffer,
PixelDatatype,
RenderState,
ShaderCache,
@@ -824,7 +822,7 @@ define([
/**
* Gets an object representing the currently bound framebuffer. While this instance is not an actual
* {@link Framebuffer}, it is used to represent the default framebuffer in calls to
- * {@link Texture.FromFramebuffer}.
+ * {@link Texture.fromFramebuffer}.
* @memberof Context.prototype
* @type {Object}
*/
@@ -1158,10 +1156,6 @@ define([
});
};
- Context.prototype.createPickFramebuffer = function() {
- return new PickFramebuffer(this);
- };
-
/**
* Gets the object associated with a pick color.
*
diff --git a/Source/Renderer/DrawCommand.js b/Source/Renderer/DrawCommand.js
index d9fc70db0d4e..b45e86c7144a 100644
--- a/Source/Renderer/DrawCommand.js
+++ b/Source/Renderer/DrawCommand.js
@@ -39,6 +39,7 @@ define([
this._castShadows = defaultValue(options.castShadows, false);
this._receiveShadows = defaultValue(options.receiveShadows, false);
this._pickId = options.pickId;
+ this._pickOnly = defaultValue(options.pickOnly, false);
this.dirty = true;
this.lastDirtyTime = 0;
@@ -471,6 +472,19 @@ define([
this.dirty = true;
}
}
+ },
+ /**
+ * Whether this command should be executed in the pick pass only.
+ *
+ * @memberof DrawCommand.prototype
+ * @type {Boolean}
+ * @default false
+ * @readonly
+ */
+ pickOnly : {
+ get : function() {
+ return this._pickOnly;
+ }
}
});
@@ -506,6 +520,7 @@ define([
result._castShadows = command._castShadows;
result._receiveShadows = command._receiveShadows;
result._pickId = command._pickId;
+ result._pickOnly = command._pickOnly;
result.dirty = true;
result.lastDirtyTime = 0;
diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js
index 353d0ae73088..12df78c6ff45 100644
--- a/Source/Scene/Camera.js
+++ b/Source/Scene/Camera.js
@@ -1006,7 +1006,7 @@ define([
}
var scene = this._scene;
- var globe = scene._globe;
+ var globe = scene.globe;
var rayIntersection;
var depthIntersection;
diff --git a/Source/Scene/Cesium3DTileBatchTable.js b/Source/Scene/Cesium3DTileBatchTable.js
index e4885fac3e9a..50af0168750a 100644
--- a/Source/Scene/Cesium3DTileBatchTable.js
+++ b/Source/Scene/Cesium3DTileBatchTable.js
@@ -1253,7 +1253,6 @@ define([
for (var i = commandStart; i < commandEnd; ++i) {
var command = commandList[i];
var derivedCommands = command.derivedCommands.tileset;
- // Command may be marked dirty from Model shader recompilation for clipping planes
if (!defined(derivedCommands) || command.dirty) {
derivedCommands = {};
command.derivedCommands.tileset = derivedCommands;
@@ -1261,13 +1260,10 @@ define([
command.dirty = false;
}
- updateDerivedCommand(derivedCommands.originalCommand, command);
-
if (styleCommandsNeeded !== StyleCommandsNeeded.ALL_OPAQUE) {
if (!defined(derivedCommands.translucent)) {
derivedCommands.translucent = deriveTranslucentCommand(derivedCommands.originalCommand);
}
- updateDerivedCommand(derivedCommands.translucent, command);
}
if (bivariateVisibilityTest) {
@@ -1280,7 +1276,6 @@ define([
if (!defined(derivedCommands.stencil) || tile._selectionDepth !== getLastSelectionDepth(derivedCommands.stencil)) {
derivedCommands.stencil = deriveStencilCommand(derivedCommands.originalCommand, tile._selectionDepth);
}
- updateDerivedCommand(derivedCommands.stencil, command);
}
var opaqueCommand = bivariateVisibilityTest ? derivedCommands.stencil : derivedCommands.originalCommand;
@@ -1316,12 +1311,6 @@ define([
}
};
- function updateDerivedCommand(derivedCommand, command) {
- derivedCommand.castShadows = command.castShadows;
- derivedCommand.receiveShadows = command.receiveShadows;
- derivedCommand.primitiveType = command.primitiveType;
- }
-
function getStyleCommandsNeeded(batchTable) {
var translucentFeaturesLength = batchTable._translucentFeaturesLength;
diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js
index aa7f6d06ab3e..bc5b8614e469 100644
--- a/Source/Scene/ClassificationPrimitive.js
+++ b/Source/Scene/ClassificationPrimitive.js
@@ -802,7 +802,8 @@ define([
if (!defined(command)) {
command = pickCommands[j] = new DrawCommand({
owner : classificationPrimitive,
- primitiveType : primitive._primitiveType
+ primitiveType : primitive._primitiveType,
+ pickOnly : true
});
}
@@ -820,7 +821,8 @@ define([
if (!defined(command)) {
command = pickCommands[j + 1] = new DrawCommand({
owner : classificationPrimitive,
- primitiveType : primitive._primitiveType
+ primitiveType : primitive._primitiveType,
+ pickOnly : true
});
}
@@ -838,7 +840,8 @@ define([
if (!defined(command)) {
command = pickCommands[j + 2] = new DrawCommand({
owner : classificationPrimitive,
- primitiveType : primitive._primitiveType
+ primitiveType : primitive._primitiveType,
+ pickOnly : true
});
}
diff --git a/Source/Scene/DepthPlane.js b/Source/Scene/DepthPlane.js
index 4df50d2663ef..ebb85625175a 100644
--- a/Source/Scene/DepthPlane.js
+++ b/Source/Scene/DepthPlane.js
@@ -103,7 +103,7 @@ define([
return depthQuadScratch;
}
- DepthPlane.prototype.update = function(frameState, useLogDepth) {
+ DepthPlane.prototype.update = function(frameState) {
this._mode = frameState.mode;
if (frameState.mode !== SceneMode.SCENE3D) {
return;
@@ -111,6 +111,7 @@ define([
var context = frameState.context;
var ellipsoid = frameState.mapProjection.ellipsoid;
+ var useLogDepth = frameState.useLogDepth;
if (!defined(this._command)) {
this._rs = RenderState.fromCache({ // Write depth, not color
diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js
index 2311182569a4..c5250a58fd92 100644
--- a/Source/Scene/EllipsoidPrimitive.js
+++ b/Source/Scene/EllipsoidPrimitive.js
@@ -8,8 +8,6 @@ define([
'../Core/destroyObject',
'../Core/DeveloperError',
'../Core/Matrix4',
- '../Core/OrthographicFrustum',
- '../Core/OrthographicOffCenterFrustum',
'../Core/VertexFormat',
'../Renderer/BufferUsage',
'../Renderer/DrawCommand',
@@ -34,8 +32,6 @@ define([
destroyObject,
DeveloperError,
Matrix4,
- OrthographicFrustum,
- OrthographicOffCenterFrustum,
VertexFormat,
BufferUsage,
DrawCommand,
@@ -213,7 +209,8 @@ define([
owner : defaultValue(options._owner, this)
});
this._pickCommand = new DrawCommand({
- owner : defaultValue(options._owner, this)
+ owner : defaultValue(options._owner, this),
+ pickOnly : true
});
var that = this;
@@ -354,8 +351,7 @@ define([
var lightingChanged = this.onlySunLighting !== this._onlySunLighting;
this._onlySunLighting = this.onlySunLighting;
- var frustum = frameState.camera.frustum;
- var useLogDepth = context.fragmentDepth && !(frustum instanceof OrthographicFrustum || frustum instanceof OrthographicOffCenterFrustum);
+ var useLogDepth = frameState.useLogDepth;
var useLogDepthChanged = this._useLogDepth !== useLogDepth;
this._useLogDepth = useLogDepth;
diff --git a/Source/Scene/FrameState.js b/Source/Scene/FrameState.js
index 6d0c3d8da2b3..985172d6c80d 100644
--- a/Source/Scene/FrameState.js
+++ b/Source/Scene/FrameState.js
@@ -138,6 +138,7 @@ define([
* @default false
*/
render : false,
+
/**
* true
if the primitive should update for a picking pass, false
otherwise.
*
@@ -232,7 +233,7 @@ define([
*/
this.terrainExaggeration = 1.0;
- this.shadowHints = {
+ this.shadowState = {
/**
* Whether there are any active shadow maps this frame.
* @type {Boolean}
@@ -330,6 +331,22 @@ define([
* @type {Color}
*/
this.invertClassificationColor = undefined;
+
+ /**
+ * Whether or not the scene uses a logarithmic depth buffer.
+ *
+ * @type {Boolean}
+ * @default false
+ */
+ this.useLogDepth = false;
+
+ /**
+ * Whether or not the scene's logarithmic depth buffer usage changed since last frame.
+ *
+ * @type {Boolean}
+ * @default false
+ */
+ this.useLogDepthDirty = false;
}
/**
diff --git a/Source/Scene/GlobeDepth.js b/Source/Scene/GlobeDepth.js
index 013c9c3539ca..81dc9f43cf55 100644
--- a/Source/Scene/GlobeDepth.js
+++ b/Source/Scene/GlobeDepth.js
@@ -239,9 +239,9 @@ define([
executeDebugGlobeDepth(this, context, passState, useLogDepth);
};
- GlobeDepth.prototype.update = function(context, passState) {
- var width = context.drawingBufferWidth;
- var height = context.drawingBufferHeight;
+ GlobeDepth.prototype.update = function(context, passState, viewport) {
+ var width = viewport.width;
+ var height = viewport.height;
updateFramebuffers(this, context, width, height);
updateCopyCommands(this, context, width, height, passState);
diff --git a/Source/Scene/OIT.js b/Source/Scene/OIT.js
index 57e083efe409..c089ea7eda17 100644
--- a/Source/Scene/OIT.js
+++ b/Source/Scene/OIT.js
@@ -540,7 +540,7 @@ define([
var framebuffer = passState.framebuffer;
var length = commands.length;
- var lightShadowsEnabled = scene.frameState.shadowHints.lightShadowsEnabled;
+ var lightShadowsEnabled = scene.frameState.shadowState.lightShadowsEnabled;
passState.framebuffer = oit._adjustTranslucentFBO;
oit._adjustTranslucentCommand.execute(context, passState);
@@ -588,7 +588,7 @@ define([
var framebuffer = passState.framebuffer;
var length = commands.length;
- var lightShadowsEnabled = scene.frameState.shadowHints.lightShadowsEnabled;
+ var lightShadowsEnabled = scene.frameState.shadowState.lightShadowsEnabled;
passState.framebuffer = oit._adjustTranslucentFBO;
oit._adjustTranslucentCommand.execute(context, passState);
diff --git a/Source/Scene/PickDepth.js b/Source/Scene/PickDepth.js
index f812a34317e9..6e643747762c 100644
--- a/Source/Scene/PickDepth.js
+++ b/Source/Scene/PickDepth.js
@@ -1,4 +1,5 @@
define([
+ '../Core/Cartesian4',
'../Core/defined',
'../Core/destroyObject',
'../Core/PixelFormat',
@@ -8,6 +9,7 @@ define([
'../Renderer/ShaderSource',
'../Renderer/Texture'
], function(
+ Cartesian4,
defined,
destroyObject,
PixelFormat,
@@ -22,7 +24,7 @@ define([
* @private
*/
function PickDepth() {
- this.framebuffer = undefined;
+ this._framebuffer = undefined;
this._depthTexture = undefined;
this._textureToCopy = undefined;
@@ -73,7 +75,7 @@ define([
}
function destroyFramebuffers(pickDepth) {
- pickDepth.framebuffer = pickDepth.framebuffer && !pickDepth.framebuffer.isDestroyed() && pickDepth.framebuffer.destroy();
+ pickDepth._framebuffer = pickDepth._framebuffer && !pickDepth._framebuffer.isDestroyed() && pickDepth._framebuffer.destroy();
}
function createTextures(pickDepth, context, width, height) {
@@ -92,7 +94,7 @@ define([
createTextures(pickDepth, context, width, height);
- pickDepth.framebuffer = new Framebuffer({
+ pickDepth._framebuffer = new Framebuffer({
context : context,
colorTextures : [pickDepth._depthTexture],
destroyAttachments : false
@@ -105,7 +107,7 @@ define([
var texture = pickDepth._depthTexture;
var textureChanged = !defined(texture) || texture.width !== width || texture.height !== height;
- if (!defined(pickDepth.framebuffer) || textureChanged) {
+ if (!defined(pickDepth._framebuffer) || textureChanged) {
createFramebuffers(pickDepth, context, width, height);
}
}
@@ -131,7 +133,7 @@ define([
}
pickDepth._textureToCopy = depthTexture;
- pickDepth._copyDepthCommand.framebuffer = pickDepth.framebuffer;
+ pickDepth._copyDepthCommand.framebuffer = pickDepth._framebuffer;
}
PickDepth.prototype.executeDebugPickDepth = function(context, passState, useLogDepth) {
@@ -143,6 +145,23 @@ define([
updateCopyCommands(this, context, depthTexture);
};
+ var scratchPackedDepth = new Cartesian4();
+ var packedDepthScale = new Cartesian4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0);
+
+ PickDepth.prototype.getDepth = function(context, x, y) {
+ var pixels = context.readPixels({
+ x : x,
+ y : y,
+ width : 1,
+ height : 1,
+ framebuffer : this._framebuffer
+ });
+
+ var packedDepth = Cartesian4.unpack(pixels, 0, scratchPackedDepth);
+ Cartesian4.divideByScalar(packedDepth, 255.0, packedDepth);
+ return Cartesian4.dot(packedDepth, packedDepthScale);
+ };
+
PickDepth.prototype.executeCopyDepth = function(context, passState) {
this._copyDepthCommand.execute(context, passState);
};
diff --git a/Source/Scene/PickDepthFramebuffer.js b/Source/Scene/PickDepthFramebuffer.js
new file mode 100644
index 000000000000..0fad5bd9ccb4
--- /dev/null
+++ b/Source/Scene/PickDepthFramebuffer.js
@@ -0,0 +1,103 @@
+define([
+ '../Core/BoundingRectangle',
+ '../Core/Color',
+ '../Core/defaultValue',
+ '../Core/defined',
+ '../Core/destroyObject',
+ '../Core/PixelFormat',
+ '../Renderer/Framebuffer',
+ '../Renderer/PassState',
+ '../Renderer/PixelDatatype',
+ '../Renderer/Renderbuffer',
+ '../Renderer/RenderbufferFormat',
+ '../Renderer/Texture'
+ ], function(
+ BoundingRectangle,
+ Color,
+ defaultValue,
+ defined,
+ destroyObject,
+ PixelFormat,
+ Framebuffer,
+ PassState,
+ PixelDatatype,
+ Renderbuffer,
+ RenderbufferFormat,
+ Texture) {
+ 'use strict';
+
+ /**
+ * @private
+ */
+ function PickDepthFramebuffer() {
+ this._depthStencilTexture = undefined;
+ this._framebuffer = undefined;
+ this._passState = undefined;
+ }
+
+ function destroyResources(pickDepth) {
+ pickDepth._framebuffer = pickDepth._framebuffer && pickDepth._framebuffer.destroy();
+ pickDepth._depthStencilTexture = pickDepth._depthStencilTexture && pickDepth._depthStencilTexture.destroy();
+ }
+
+ function createResources(pickDepth, context) {
+ var width = context.drawingBufferWidth;
+ var height = context.drawingBufferHeight;
+
+ pickDepth._depthStencilTexture = new Texture({
+ context : context,
+ width : width,
+ height : height,
+ pixelFormat : PixelFormat.DEPTH_STENCIL,
+ pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8
+ });
+
+ pickDepth._framebuffer = new Framebuffer({
+ context : context,
+ depthStencilTexture : pickDepth._depthStencilTexture,
+ destroyAttachments : false
+ });
+
+ var passState = new PassState(context);
+ passState.blendingEnabled = false;
+ passState.scissorTest = {
+ enabled : true,
+ rectangle : new BoundingRectangle()
+ };
+ passState.viewport = new BoundingRectangle();
+ pickDepth._passState = passState;
+ }
+
+ PickDepthFramebuffer.prototype.update = function(context, drawingBufferPosition, viewport) {
+ var width = viewport.width;
+ var height = viewport.height;
+
+ if (!defined(this._framebuffer) || width !== this._depthStencilTexture.width || height !== this._depthStencilTexture.height) {
+ destroyResources(this);
+ createResources(this, context);
+ }
+
+ var framebuffer = this._framebuffer;
+ var passState = this._passState;
+ passState.framebuffer = framebuffer;
+ passState.viewport.width = width;
+ passState.viewport.height = height;
+ passState.scissorTest.rectangle.x = drawingBufferPosition.x;
+ passState.scissorTest.rectangle.y = height - drawingBufferPosition.y;
+ passState.scissorTest.rectangle.width = 1;
+ passState.scissorTest.rectangle.height = 1;
+
+ return passState;
+ };
+
+ PickDepthFramebuffer.prototype.isDestroyed = function() {
+ return false;
+ };
+
+ PickDepthFramebuffer.prototype.destroy = function() {
+ destroyResources(this);
+ return destroyObject(this);
+ };
+
+ return PickDepthFramebuffer;
+});
diff --git a/Source/Renderer/PickFramebuffer.js b/Source/Scene/PickFramebuffer.js
similarity index 93%
rename from Source/Renderer/PickFramebuffer.js
rename to Source/Scene/PickFramebuffer.js
index 651055d2bbaa..c47a59c40104 100644
--- a/Source/Renderer/PickFramebuffer.js
+++ b/Source/Scene/PickFramebuffer.js
@@ -4,11 +4,11 @@ define([
'../Core/defaultValue',
'../Core/defined',
'../Core/destroyObject',
- './Framebuffer',
- './PassState',
- './Renderbuffer',
- './RenderbufferFormat',
- './Texture'
+ '../Renderer/Framebuffer',
+ '../Renderer/PassState',
+ '../Renderer/Renderbuffer',
+ '../Renderer/RenderbufferFormat',
+ '../Renderer/Texture'
], function(
BoundingRectangle,
Color,
@@ -41,10 +41,10 @@ define([
this._width = 0;
this._height = 0;
}
- PickFramebuffer.prototype.begin = function(screenSpaceRectangle) {
+ PickFramebuffer.prototype.begin = function(screenSpaceRectangle, viewport) {
var context = this._context;
- var width = context.drawingBufferWidth;
- var height = context.drawingBufferHeight;
+ var width = viewport.width;
+ var height = viewport.height;
BoundingRectangle.clone(screenSpaceRectangle, this._passState.scissorTest.rectangle);
@@ -63,6 +63,8 @@ define([
})],
depthStencilRenderbuffer : new Renderbuffer({
context : context,
+ width : width,
+ height : height,
format : RenderbufferFormat.DEPTH_STENCIL
})
});
diff --git a/Source/Scene/PostProcessStage.js b/Source/Scene/PostProcessStage.js
index 97751e375116..7d6713ddac42 100644
--- a/Source/Scene/PostProcessStage.js
+++ b/Source/Scene/PostProcessStage.js
@@ -849,6 +849,7 @@ define([
/**
* A function that will be called before execute. Used to create WebGL resources and load any textures.
* @param {Context} context The context.
+ * @param {Boolean} useLogDepth Whether the scene uses a logarithmic depth buffer.
* @private
*/
PostProcessStage.prototype.update = function(context, useLogDepth) {
@@ -910,6 +911,7 @@ define([
* @param {Context} context The context.
* @param {Texture} colorTexture The input color texture.
* @param {Texture} depthTexture The input depth texture.
+ * @param {Texture} idTexture The id texture.
* @private
*/
PostProcessStage.prototype.execute = function(context, colorTexture, depthTexture, idTexture) {
diff --git a/Source/Scene/PostProcessStageCollection.js b/Source/Scene/PostProcessStageCollection.js
index b46608f1afcb..deb78a5f3bec 100644
--- a/Source/Scene/PostProcessStageCollection.js
+++ b/Source/Scene/PostProcessStageCollection.js
@@ -464,6 +464,7 @@ define([
* Called before the post-process stages in the collection are executed. Calls update for each stage and creates WebGL resources.
*
* @param {Context} context The context.
+ * @param {Boolean} useLogDepth Whether the scene uses a logarithmic depth buffer.
*
* @private
*/
@@ -621,6 +622,7 @@ define([
* @param {Context} context The context.
* @param {Texture} colorTexture The color texture rendered to by the scene.
* @param {Texture} depthTexture The depth texture written to by the scene.
+ * @param {Texture} idTexture The id texture written to by the scene.
*
* @private
*/
diff --git a/Source/Scene/PostProcessStageComposite.js b/Source/Scene/PostProcessStageComposite.js
index 847a368c83ee..f2b8777567e5 100644
--- a/Source/Scene/PostProcessStageComposite.js
+++ b/Source/Scene/PostProcessStageComposite.js
@@ -294,6 +294,7 @@ define([
/**
* A function that will be called before execute. Updates each post-process stage in the composite.
* @param {Context} context The context.
+ * @param {Boolean} useLogDepth Whether the scene uses a logarithmic depth buffer.
* @private
*/
PostProcessStageComposite.prototype.update = function(context, useLogDepth) {
diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js
index 68242abcacd9..fa2c9f4d2baf 100644
--- a/Source/Scene/Scene.js
+++ b/Source/Scene/Scene.js
@@ -4,7 +4,6 @@ define([
'../Core/BoxGeometry',
'../Core/Cartesian2',
'../Core/Cartesian3',
- '../Core/Cartesian4',
'../Core/Cartographic',
'../Core/Color',
'../Core/ColorGeometryInstanceAttribute',
@@ -21,9 +20,7 @@ define([
'../Core/GeographicProjection',
'../Core/GeometryInstance',
'../Core/GeometryPipeline',
- '../Core/getTimestamp',
'../Core/Intersect',
- '../Core/Interval',
'../Core/JulianDate',
'../Core/Math',
'../Core/Matrix4',
@@ -45,13 +42,13 @@ define([
'../Renderer/DrawCommand',
'../Renderer/Framebuffer',
'../Renderer/Pass',
- '../Renderer/PassState',
'../Renderer/PixelDatatype',
'../Renderer/ShaderProgram',
'../Renderer/ShaderSource',
'../Renderer/Texture',
'./BrdfLutGenerator',
'./Camera',
+ './Cesium3DTileFeature',
'./CreditDisplay',
'./DebugCameraPrimitive',
'./DepthPlane',
@@ -59,33 +56,30 @@ define([
'./DeviceOrientationCameraController',
'./Fog',
'./FrameState',
- './FrustumCommands',
'./GlobeDepth',
'./InvertClassification',
'./JobScheduler',
'./MapMode2D',
- './OIT',
'./PerformanceDisplay',
'./PerInstanceColorAppearance',
'./PickDepth',
'./PostProcessStageCollection',
'./Primitive',
'./PrimitiveCollection',
- './SceneFramebuffer',
'./SceneMode',
'./SceneTransforms',
'./SceneTransitioner',
'./ScreenSpaceCameraController',
'./ShadowMap',
'./SunPostProcess',
- './TweenCollection'
+ './TweenCollection',
+ './View'
], function(
BoundingRectangle,
BoundingSphere,
BoxGeometry,
Cartesian2,
Cartesian3,
- Cartesian4,
Cartographic,
Color,
ColorGeometryInstanceAttribute,
@@ -102,9 +96,7 @@ define([
GeographicProjection,
GeometryInstance,
GeometryPipeline,
- getTimestamp,
Intersect,
- Interval,
JulianDate,
CesiumMath,
Matrix4,
@@ -126,13 +118,13 @@ define([
DrawCommand,
Framebuffer,
Pass,
- PassState,
PixelDatatype,
ShaderProgram,
ShaderSource,
Texture,
BrdfLutGenerator,
Camera,
+ Cesium3DTileFeature,
CreditDisplay,
DebugCameraPrimitive,
DepthPlane,
@@ -140,26 +132,24 @@ define([
DeviceOrientationCameraController,
Fog,
FrameState,
- FrustumCommands,
GlobeDepth,
InvertClassification,
JobScheduler,
MapMode2D,
- OIT,
PerformanceDisplay,
PerInstanceColorAppearance,
PickDepth,
PostProcessStageCollection,
Primitive,
PrimitiveCollection,
- SceneFramebuffer,
SceneMode,
SceneTransforms,
SceneTransitioner,
ScreenSpaceCameraController,
ShadowMap,
SunPostProcess,
- TweenCollection) {
+ TweenCollection,
+ View) {
'use strict';
var requestRenderAfterFrame = function (scene) {
@@ -276,14 +266,6 @@ define([
this._removeCreditContainer = !hasCreditContainer;
this._creditContainer = creditContainer;
- var ps = new PassState(context);
- ps.viewport = new BoundingRectangle();
- ps.viewport.x = 0;
- ps.viewport.y = 0;
- ps.viewport.width = context.drawingBufferWidth;
- ps.viewport.height = context.drawingBufferHeight;
- this._passState = ps;
-
this._canvas = canvas;
this._context = context;
this._computeEngine = new ComputeEngine(context);
@@ -293,7 +275,6 @@ define([
this._logDepthBuffer = context.fragmentDepth;
this._logDepthBufferDirty = true;
- this._updateFrustums = false;
this._tweens = new TweenCollection();
@@ -302,28 +283,12 @@ define([
this._sunPostProcess = undefined;
this._computeCommandList = [];
- this._frustumCommandsList = [];
this._overlayCommandList = [];
- this._pickFramebuffer = undefined;
-
this._useOIT = defaultValue(options.orderIndependentTranslucency, true);
this._executeOITFunction = undefined;
- var globeDepth;
- if (context.depthTexture) {
- globeDepth = new GlobeDepth();
- }
-
- var oit;
- if (this._useOIT && defined(globeDepth)) {
- oit = new OIT(context);
- }
-
- this._globeDepth = globeDepth;
this._depthPlane = new DepthPlane();
- this._oit = oit;
- this._sceneFramebuffer = new SceneFramebuffer();
this._clearColorCommand = new ClearCommand({
color : new Color(),
@@ -338,13 +303,6 @@ define([
stencil : 0
});
- this._pickDepths = [];
- this._debugGlobeDepths = [];
-
- this._pickDepthPassState = undefined;
- this._pickDepthFramebuffer = undefined;
- this._pickDepthFramebufferWidth = undefined;
- this._pickDepthFramebufferHeight = undefined;
this._depthOnlyRenderStateCache = {};
this._pickRenderStateCache = {};
@@ -357,9 +315,6 @@ define([
this._preRender = new Event();
this._postRender = new Event();
- this._cameraStartFired = false;
- this._cameraMovedTime = undefined;
-
this._pickPositionCache = {};
this._pickPositionCacheDirty = false;
@@ -501,6 +456,16 @@ define([
*/
this.nearToFarDistance2D = 1.75e6;
+ /**
+ * Determines the uniform depth size in meters of each frustum of the multifrustum in orthographic. If a primitive or model
+ * 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.
+ *
+ * @type {Number}
+ * @default 1.75e6
+ */
+ this.nearToFarDistanceOrthographic = 1.75e6;
+
/**
* This property is for debugging only; it is not for production use.
*
@@ -561,8 +526,6 @@ define([ */ this.debugShowFrustums = false; - this._debugFrustumStatistics = undefined; - /** * This property is for debugging only; it is not for production use. *
@@ -622,7 +585,7 @@ define([
this.useDepthPicking = true;
/**
- * When true
, enables picking translucent geometry using the depth buffer. Note that {@link Scene#useDepthPicking} must also be true for this enabling to work.
+ * When true
, enables picking translucent geometry using the depth buffer. Note that {@link Scene#useDepthPicking} must also be true for enabling this to work.
*
*
* Render must be called between picks. @@ -720,19 +683,9 @@ define([ this._performanceDisplay = undefined; this._debugVolume = undefined; - var camera = new Camera(this); - this._camera = camera; this._screenSpaceCameraController = new ScreenSpaceCameraController(this); this._mapMode2D = defaultValue(options.mapMode2D, MapMode2D.INFINITE_SCROLL); - if (this._logDepthBuffer) { - this._camera.frustum.near = 0.1; - this._camera.frustum.far = 10000000000.0; - } - - this._cameraClone = Camera.clone(camera); - this._frustumChanged = true; - // 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 @@ -751,13 +704,15 @@ define([ clearGlobeDepth : false, useDepthPlane : false, + renderTranslucentDepthForPick : false, originalFramebuffer : undefined, useGlobeDepthFramebuffer : false, useOIT : false, useInvertClassification : false, usePostProcess : false, - usePostProcessSelected : false + usePostProcessSelected : false, + useWebVR : false }; this._useWebVR = false; @@ -796,20 +751,24 @@ define([ */ 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 = []; - // initial guess at frustums. - var near = camera.frustum.near; - var far = camera.frustum.far; - var farToNearRatio = this._logDepthBuffer ? this.logarithmicDepthFarToNearRatio : this.farToNearRatio; + 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; + } - var numFrustums = Math.ceil(Math.log(far / near) / Math.log(farToNearRatio)); - updateFrustums(near, far, farToNearRatio, numFrustums, this._logDepthBuffer, this._frustumCommandsList, false, undefined); + this._defaultView = new View(this, camera, viewport); + this._view = this._defaultView; - // give frameState, camera, and screen space camera controller initial state before rendering + // Give frameState, camera, and screen space camera controller initial state before rendering updateFrameState(this, 0.0, JulianDate.now()); this.initializeFrame(); } @@ -843,13 +802,13 @@ define([ }, /** - * The drawingBufferWidth of the underlying GL context. + * 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-drawingBufferWidth|drawingBufferWidth} + * @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight} */ drawingBufferHeight : { get : function() { @@ -969,10 +928,13 @@ define([ */ camera : { get : function() { - return this._camera; + return this._view.camera; + }, + set : function(camera) { + // For internal use only. Documentation is still @readonly. + this._view.camera = camera; } }, - // TODO: setCamera /** * Gets the controller for camera input handling. @@ -1227,7 +1189,7 @@ define([ */ debugFrustumStatistics : { get : function() { - return this._debugFrustumStatistics; + return this._view.debugFrustumStatistics; } }, @@ -1253,7 +1215,7 @@ define([ */ orderIndependentTranslucency : { get : function() { - return defined(this._oit); + return this._useOIT; } }, @@ -1300,6 +1262,19 @@ define([ } }, + /** + * 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 @@ -1309,7 +1284,7 @@ define([ */ numberOfFrustums : { get : function() { - return this._frustumCommandsList.length; + return this._view.frustumCommandsList.length; } }, @@ -1349,14 +1324,14 @@ define([ this._deviceOrientationCameraController = new DeviceOrientationCameraController(this); } - this._aspectRatioVR = this._camera.frustum.aspectRatio; + this._aspectRatioVR = this.camera.frustum.aspectRatio; } else { this._frameState.creditDisplay.container.style.visibility = 'visible'; this._cameraVR = undefined; this._deviceOrientationCameraController = this._deviceOrientationCameraController && !this._deviceOrientationCameraController.isDestroyed() && this._deviceOrientationCameraController.destroy(); - this._camera.frustum.aspectRatio = this._aspectRatioVR; - this._camera.frustum.xOffset = 0.0; + this.camera.frustum.aspectRatio = this._aspectRatioVR; + this.camera.frustum.xOffset = 0.0; } } }, @@ -1425,7 +1400,7 @@ define([ if (this._logDepthBuffer !== value) { this._logDepthBuffer = value; this._logDepthBufferDirty = true; - this._updateFrustums = true; + this._defaultView.updateFrustums = true; } } }, @@ -1435,7 +1410,7 @@ define([ */ opaqueFrustumNearOffset : { get : function() { - return this._logDepthBuffer ? 0.9 : 0.9999; + return this._frameState.useLogDepth ? 0.9 : 0.9999; } } }); @@ -1452,93 +1427,86 @@ define([ ((format === 'WEBGL_compressed_texture_etc1' || format === 'etc1') && context.etc1); }; - var scratchPosition0 = new Cartesian3(); - var scratchPosition1 = new Cartesian3(); - function maxComponent(a, b) { - var x = Math.max(Math.abs(a.x), Math.abs(b.x)); - var y = Math.max(Math.abs(a.y), Math.abs(b.y)); - var z = Math.max(Math.abs(a.z), Math.abs(b.z)); - return Math.max(Math.max(x, y), z); - } + function updateDerivedCommands(scene, command, shadowsDirty) { + var frameState = scene._frameState; + var context = scene._context; + var oit = scene._view.oit; + var lightShadowMaps = frameState.shadowState.lightShadowMaps; + var lightShadowsEnabled = frameState.shadowState.lightShadowsEnabled; + + var derivedCommands = command.derivedCommands; + + if (lightShadowsEnabled && command.receiveShadows) { + derivedCommands.shadows = ShadowMap.createReceiveDerivedCommand(lightShadowMaps, command, shadowsDirty, context, derivedCommands.shadows); + } + + if (defined(command.pickId)) { + derivedCommands.picking = DerivedCommand.createPickDerivedCommand(scene, command, context, derivedCommands.picking); + } - function cameraEqual(camera0, camera1, epsilon) { - var scalar = 1 / Math.max(1, maxComponent(camera0.position, camera1.position)); - Cartesian3.multiplyByScalar(camera0.position, scalar, scratchPosition0); - Cartesian3.multiplyByScalar(camera1.position, scalar, scratchPosition1); - return Cartesian3.equalsEpsilon(scratchPosition0, scratchPosition1, epsilon) && - Cartesian3.equalsEpsilon(camera0.direction, camera1.direction, epsilon) && - Cartesian3.equalsEpsilon(camera0.up, camera1.up, epsilon) && - Cartesian3.equalsEpsilon(camera0.right, camera1.right, epsilon) && - Matrix4.equalsEpsilon(camera0.transform, camera1.transform, epsilon) && - camera0.frustum.equalsEpsilon(camera1.frustum, epsilon); + if (command.pass === Pass.TRANSLUCENT && defined(oit) && oit.isSupported()) { + if (lightShadowsEnabled && command.receiveShadows) { + derivedCommands.oit = defined(derivedCommands.oit) ? derivedCommands.oit : {}; + derivedCommands.oit.shadows = oit.createDerivedCommands(derivedCommands.shadows.receiveCommand, context, derivedCommands.oit.shadows); + } else { + derivedCommands.oit = oit.createDerivedCommands(command, context, derivedCommands.oit); + } + } + + if (!command.pickOnly) { + derivedCommands.depth = DerivedCommand.createDepthOnlyDerivedCommand(scene, command, context, derivedCommands.depth); + } + + derivedCommands.originalCommand = command; } - function updateDerivedCommands(scene, command) { - var frameState = scene.frameState; - var context = scene._context; - var shadowsEnabled = frameState.shadowHints.shadowsEnabled; - var shadowMaps = frameState.shadowHints.shadowMaps; - var lightShadowMaps = frameState.shadowHints.lightShadowMaps; - var lightShadowsEnabled = frameState.shadowHints.lightShadowsEnabled; + /** + * @private + */ + Scene.prototype.updateDerivedCommands = function(command) { + if (!defined(command.derivedCommands)) { + // Is not a DrawCommand + return; + } + + var frameState = this._frameState; + var context = this._context; // Update derived commands when any shadow maps become dirty var shadowsDirty = false; - var lastDirtyTime = frameState.shadowHints.lastDirtyTime; + var lastDirtyTime = frameState.shadowState.lastDirtyTime; if (command.lastDirtyTime !== lastDirtyTime) { command.lastDirtyTime = lastDirtyTime; command.dirty = true; shadowsDirty = true; } + var useLogDepth = frameState.useLogDepth; var derivedCommands = command.derivedCommands; - if ((scene._logDepthBufferDirty || scene._frustumChanged || command.dirty) && defined(derivedCommands)) { - command.dirty = false; + var hasLogDepthDerivedCommands = defined(derivedCommands.logDepth); + var hasDerivedCommands = defined(derivedCommands.originalCommand); + var needsLogDepthDerivedCommands = useLogDepth && !hasLogDepthDerivedCommands; + var needsDerivedCommands = !useLogDepth && !hasDerivedCommands; + command.dirty = command.dirty || needsLogDepthDerivedCommands || needsDerivedCommands; - var frustum = scene.camera.frustum; - var useLogDepth = scene._logDepthBuffer && !(frustum instanceof OrthographicFrustum || frustum instanceof OrthographicOffCenterFrustum); - var logDepthCommand; - var logDepthDerivedCommands; - if (useLogDepth) { - derivedCommands.logDepth = DerivedCommand.createLogDepthCommand(command, context, derivedCommands.logDepth); - logDepthCommand = derivedCommands.logDepth.command; - logDepthDerivedCommands = logDepthCommand.derivedCommands; - } else { - derivedCommands.logDepth = undefined; - } - - if (shadowsEnabled && (command.receiveShadows || command.castShadows)) { - derivedCommands.shadows = ShadowMap.createDerivedCommands(shadowMaps, lightShadowMaps, command, shadowsDirty, context, derivedCommands.shadows); - if (useLogDepth) { - logDepthDerivedCommands.shadows = ShadowMap.createDerivedCommands(shadowMaps, lightShadowMaps, logDepthCommand, shadowsDirty, context, logDepthDerivedCommands.shadows); - } - } - - if (useLogDepth) { - command = logDepthCommand; - derivedCommands = logDepthDerivedCommands; - } + if (command.dirty) { + command.dirty = false; - if (defined(command.pickId)) { - derivedCommands.picking = DerivedCommand.createPickDerivedCommand(scene, command, context, derivedCommands.picking); + var shadowMaps = frameState.shadowState.shadowMaps; + var shadowsEnabled = frameState.shadowState.shadowsEnabled; + if (shadowsEnabled && command.castShadows) { + derivedCommands.shadows = ShadowMap.createCastDerivedCommand(shadowMaps, command, shadowsDirty, context, derivedCommands.shadows); } - var oit = scene._oit; - if (command.pass === Pass.TRANSLUCENT && defined(oit) && oit.isSupported()) { - if (lightShadowsEnabled && command.receiveShadows) { - derivedCommands.oit = defined(derivedCommands.oit) ? derivedCommands.oit : {}; - derivedCommands.oit.shadows = oit.createDerivedCommands(derivedCommands.shadows.receiveCommand, context, derivedCommands.oit.shadows); - } else { - derivedCommands.oit = oit.createDerivedCommands(command, context, derivedCommands.oit); - } + if (hasLogDepthDerivedCommands || needsLogDepthDerivedCommands) { + derivedCommands.logDepth = DerivedCommand.createLogDepthCommand(command, context, derivedCommands.logDepth); + updateDerivedCommands(this, derivedCommands.logDepth.command, shadowsDirty); } - - if (scene.frameState.passes.pick && !defined(command.pickId)) { - return; + if (hasDerivedCommands || needsDerivedCommands) { + updateDerivedCommands(this, command, shadowsDirty); } - - derivedCommands.depth = DerivedCommand.createDepthOnlyDerivedCommand(scene, command, context, derivedCommands.depth); } - } + }; var scratchOccluderBoundingSphere = new BoundingSphere(); var scratchOccluder; @@ -1550,7 +1518,7 @@ define([ if (scene._mode === SceneMode.SCENE3D && defined(globe) && globe.show) { var ellipsoid = globe.ellipsoid; scratchOccluderBoundingSphere.radius = ellipsoid.minimumRadius; - scratchOccluder = Occluder.fromBoundingSphere(scratchOccluderBoundingSphere, scene._camera.positionWC, scratchOccluder); + scratchOccluder = Occluder.fromBoundingSphere(scratchOccluderBoundingSphere, scene.camera.positionWC, scratchOccluder); return scratchOccluder; } @@ -1565,7 +1533,7 @@ define([ } function updateFrameState(scene, frameNumber, time) { - var camera = scene._camera; + var camera = scene.camera; var frameState = scene._frameState; frameState.commandList.length = 0; @@ -1584,6 +1552,11 @@ define([ frameState.minimumDisableDepthTestDistance = scene._minimumDisableDepthTestDistance; frameState.invertClassification = scene.invertClassification; + var useLogDepth = scene._logDepthBuffer && !(scene.camera.frustum instanceof OrthographicFrustum || scene.camera.frustum instanceof OrthographicOffCenterFrustum); + var useLogDepthDirty = useLogDepth !== frameState.useLogDepth; + frameState.useLogDepth = useLogDepth; + frameState.useLogDepthDirty = useLogDepthDirty; + scene._actualInvertClassificationColor = Color.clone(scene.invertClassificationColor, scene._actualInvertClassificationColor); if (!InvertClassification.isTranslucencySupported(scene._context)) { scene._actualInvertClassificationColor.alpha = 1.0; @@ -1600,242 +1573,18 @@ define([ clearPasses(frameState.passes); } - function updateFrustums(near, far, farToNearRatio, numFrustums, logDepth, frustumCommandsList, is2D, nearToFarDistance2D) { - frustumCommandsList.length = numFrustums; - for (var m = 0; m < numFrustums; ++m) { - var curNear; - var curFar; - - if (!is2D) { - curNear = Math.max(near, Math.pow(farToNearRatio, m) * near); - curFar = farToNearRatio * curNear; - if (!logDepth) { - curFar = Math.min(far, curFar); - } - } else { - curNear = Math.min(far - nearToFarDistance2D, near + m * nearToFarDistance2D); - curFar = Math.min(far, curNear + nearToFarDistance2D); - } - - var frustumCommands = frustumCommandsList[m]; - if (!defined(frustumCommands)) { - frustumCommands = frustumCommandsList[m] = new FrustumCommands(curNear, curFar); - } else { - frustumCommands.near = curNear; - frustumCommands.far = curFar; - } - } - } - - function insertIntoBin(scene, command, distance) { - if (scene.debugShowFrustums) { - command.debugOverlappingFrustums = 0; - } - - var frustumCommandsList = scene._frustumCommandsList; - var length = frustumCommandsList.length; - - for (var i = 0; i < length; ++i) { - var frustumCommands = frustumCommandsList[i]; - var curNear = frustumCommands.near; - var curFar = frustumCommands.far; - - if (distance.start > curFar) { - continue; - } - - if (distance.stop < curNear) { - break; - } - - var pass = command.pass; - var index = frustumCommands.indices[pass]++; - frustumCommands.commands[pass][index] = command; - - if (scene.debugShowFrustums) { - command.debugOverlappingFrustums |= (1 << i); - } - - if (command.executeInClosestFrustum) { - break; - } - } - - if (scene.debugShowFrustums) { - var cf = scene._debugFrustumStatistics.commandsInFrustums; - cf[command.debugOverlappingFrustums] = defined(cf[command.debugOverlappingFrustums]) ? cf[command.debugOverlappingFrustums] + 1 : 1; - ++scene._debugFrustumStatistics.totalCommands; - } - - updateDerivedCommands(scene, command); - } - var scratchCullingVolume = new CullingVolume(); - var distances = new Interval(); - function isVisible(command, cullingVolume, occluder) { + /** + * @private + */ + Scene.prototype.isVisible = function(command, cullingVolume, occluder) { return ((defined(command)) && ((!defined(command.boundingVolume)) || !command.cull || ((cullingVolume.computeVisibility(command.boundingVolume) !== Intersect.OUTSIDE) && (!defined(occluder) || !command.boundingVolume.isOccluded(occluder))))); - } - - function createPotentiallyVisibleSet(scene) { - var frameState = scene._frameState; - var camera = frameState.camera; - var direction = camera.directionWC; - var position = camera.positionWC; - - var computeList = scene._computeCommandList; - var overlayList = scene._overlayCommandList; - var commandList = frameState.commandList; - - if (scene.debugShowFrustums) { - scene._debugFrustumStatistics = { - totalCommands : 0, - commandsInFrustums : {} - }; - } - - var frustumCommandsList = scene._frustumCommandsList; - var numberOfFrustums = frustumCommandsList.length; - var numberOfPasses = Pass.NUMBER_OF_PASSES; - for (var n = 0; n < numberOfFrustums; ++n) { - for (var p = 0; p < numberOfPasses; ++p) { - frustumCommandsList[n].indices[p] = 0; - } - } - - computeList.length = 0; - overlayList.length = 0; - - var near = Number.MAX_VALUE; - var far = -Number.MAX_VALUE; - var undefBV = false; - - var shadowsEnabled = frameState.shadowHints.shadowsEnabled; - var shadowNear = Number.MAX_VALUE; - var shadowFar = -Number.MAX_VALUE; - var shadowClosestObjectSize = Number.MAX_VALUE; - - var occluder = (frameState.mode === SceneMode.SCENE3D) ? frameState.occluder: undefined; - var cullingVolume = frameState.cullingVolume; - - // get user culling volume minus the far plane. - var planes = scratchCullingVolume.planes; - for (var k = 0; k < 5; ++k) { - planes[k] = cullingVolume.planes[k]; - } - cullingVolume = scratchCullingVolume; - - var length = commandList.length; - for (var i = 0; i < length; ++i) { - var command = commandList[i]; - var pass = command.pass; - - if (pass === Pass.COMPUTE) { - computeList.push(command); - } else if (pass === Pass.OVERLAY) { - overlayList.push(command); - } else { - var boundingVolume = command.boundingVolume; - if (defined(boundingVolume)) { - if (!isVisible(command, cullingVolume, occluder)) { - continue; - } - - distances = boundingVolume.computePlaneDistances(position, direction, distances); - near = Math.min(near, distances.start); - far = Math.max(far, distances.stop); - - // Compute a tight near and far plane for commands that receive shadows. This helps compute - // good splits for cascaded shadow maps. Ignore commands that exceed the maximum distance. - // When moving the camera low LOD globe tiles begin to load, whose bounding volumes - // throw off the near/far fitting for the shadow map. Only update for globe tiles that the - // camera isn't inside. - if (shadowsEnabled && command.receiveShadows && (distances.start < ShadowMap.MAXIMUM_DISTANCE) && - !((pass === Pass.GLOBE) && (distances.start < -100.0) && (distances.stop > 100.0))) { - - // Get the smallest bounding volume the camera is near. This is used to place more shadow detail near the object. - var size = distances.stop - distances.start; - if ((pass !== Pass.GLOBE) && (distances.start < 100.0)) { - shadowClosestObjectSize = Math.min(shadowClosestObjectSize, size); - } - shadowNear = Math.min(shadowNear, distances.start); - shadowFar = Math.max(shadowFar, distances.stop); - } - } else { - // Clear commands don't need a bounding volume - just add the clear to all frustums. - // If another command has no bounding volume, though, we need to use the camera's - // worst-case near and far planes to avoid clipping something important. - distances.start = camera.frustum.near; - distances.stop = camera.frustum.far; - undefBV = !(command instanceof ClearCommand); - } - - insertIntoBin(scene, command, distances); - } - } - - if (undefBV) { - near = camera.frustum.near; - far = camera.frustum.far; - } else { - // The computed near plane must be between the user defined near and far planes. - // The computed far plane must between the user defined far and computed near. - // This will handle the case where the computed near plane is further than the user defined far plane. - near = Math.min(Math.max(near, camera.frustum.near), camera.frustum.far); - far = Math.max(Math.min(far, camera.frustum.far), near); - - if (shadowsEnabled) { - shadowNear = Math.min(Math.max(shadowNear, camera.frustum.near), camera.frustum.far); - shadowFar = Math.max(Math.min(shadowFar, camera.frustum.far), shadowNear); - } - } - - // Use the computed near and far for shadows - if (shadowsEnabled) { - frameState.shadowHints.nearPlane = shadowNear; - frameState.shadowHints.farPlane = shadowFar; - frameState.shadowHints.closestObjectSize = shadowClosestObjectSize; - } - - // Exploit temporal coherence. If the frustums haven't changed much, use the frustums computed - // last frame, else compute the new frustums and sort them by frustum again. - var is2D = scene.mode === SceneMode.SCENE2D; - var logDepth = scene._logDepthBuffer && !(camera.frustum instanceof OrthographicFrustum || camera.frustum instanceof OrthographicOffCenterFrustum); - var farToNearRatio = logDepth ? scene.logarithmicDepthFarToNearRatio : scene.farToNearRatio; - var numFrustums; - - if (!is2D) { - // The multifrustum for 3D/CV is non-uniformly distributed. - numFrustums = Math.ceil(Math.log(far / near) / Math.log(farToNearRatio)); - } else { - // The multifrustum for 2D is uniformly distributed. To avoid z-fighting in 2D, - // the camera is moved to just before the frustum and the frustum depth is scaled - // to be in [1.0, nearToFarDistance2D]. - far = Math.min(far, camera.position.z + scene.nearToFarDistance2D); - near = Math.min(near, far); - numFrustums = Math.ceil(Math.max(1.0, far - near) / scene.nearToFarDistance2D); - } - - if (scene._updateFrustums || (near !== Number.MAX_VALUE && (numFrustums !== numberOfFrustums || (frustumCommandsList.length !== 0 && - (near < frustumCommandsList[0].near || (far > frustumCommandsList[numberOfFrustums - 1].far && (logDepth || !CesiumMath.equalsEpsilon(far, frustumCommandsList[numberOfFrustums - 1].far, CesiumMath.EPSILON8)))))))) { - scene._updateFrustums = false; - updateFrustums(near, far, farToNearRatio, numFrustums, logDepth, frustumCommandsList, is2D, scene.nearToFarDistance2D); - createPotentiallyVisibleSet(scene); - } - - var frustumSplits = frameState.frustumSplits; - frustumSplits.length = numFrustums + 1; - for (var j = 0; j < numFrustums; ++j) { - frustumSplits[j] = frustumCommandsList[j].near; - if (j === numFrustums - 1) { - frustumSplits[j + 1] = frustumCommandsList[j].far; - } - } - } + }; function getAttributeLocations(shaderProgram) { var attributeLocations = {}; @@ -2003,9 +1752,7 @@ define([ command = commandList[0]; - var frustum = scene.camera.frustum; - var useLogDepth = scene._logDepthBuffer && !(frustum instanceof OrthographicFrustum || frustum instanceof OrthographicOffCenterFrustum); - if (useLogDepth) { + if (frameState.useLogDepth) { var logDepth = DerivedCommand.createLogDepthCommand(command, context); command = logDepth.command; } @@ -2041,7 +1788,7 @@ define([ debugShowBoundingVolume(command, scene, passState, debugFramebuffer); } - if (scene._logDepthBuffer && defined(command.derivedCommands.logDepth)) { + if (frameState.useLogDepth && defined(command.derivedCommands.logDepth)) { command = command.derivedCommands.logDepth.command; } @@ -2063,7 +1810,7 @@ define([ return; } - if (frameState.shadowHints.lightShadowsEnabled && command.receiveShadows && defined(command.derivedCommands.shadows)) { + if (frameState.shadowState.lightShadowsEnabled && command.receiveShadows && defined(command.derivedCommands.shadows)) { // If the command receives shadows, execute the derived shadows command. // Some commands, such as OIT derived commands, do not have derived shadow commands themselves // and instead shadowing is built-in. In this case execute the command regularly below. @@ -2074,12 +1821,13 @@ define([ } function executeIdCommand(command, scene, context, passState) { + var frameState = scene._frameState; var derivedCommands = command.derivedCommands; if (!defined(derivedCommands)) { return; } - if (scene._logDepthBuffer && defined(derivedCommands.logDepth)) { + if (frameState.useLogDepth && defined(derivedCommands.logDepth)) { command = derivedCommands.logDepth.command; } @@ -2100,32 +1848,47 @@ define([ function executeTranslucentCommandsSorted(scene, executeFunction, passState, commands, invertClassification) { var context = scene.context; - mergeSort(commands, translucentCompare, scene._camera.positionWC); + mergeSort(commands, translucentCompare, scene.camera.positionWC); if (defined(invertClassification)) { executeFunction(invertClassification.unclassifiedCommand, scene, context, passState); } var length = commands.length; - for (var j = 0; j < length; ++j) { - executeFunction(commands[j], scene, context, passState); + for (var i = 0; i < length; ++i) { + executeFunction(commands[i], scene, context, passState); + } + } + + function executeTranslucentCommandsUnsorted(scene, executeFunction, passState, commands, invertClassification) { + var context = scene.context; + + if (defined(invertClassification)) { + executeFunction(invertClassification.unclassifiedCommand, scene, context, passState); + } + + var length = commands.length; + for (var i = 0; i < length; ++i) { + executeFunction(commands[i], scene, context, passState); } } function getDebugGlobeDepth(scene, index) { - var globeDepth = scene._debugGlobeDepths[index]; + var globeDepths = scene._view.debugGlobeDepths; + var globeDepth = globeDepths[index]; if (!defined(globeDepth) && scene.context.depthTexture) { globeDepth = new GlobeDepth(); - scene._debugGlobeDepths[index] = globeDepth; + globeDepths[index] = globeDepth; } return globeDepth; } function getPickDepth(scene, index) { - var pickDepth = scene._pickDepths[index]; + var pickDepths = scene._view.pickDepths; + var pickDepth = pickDepths[index]; if (!defined(pickDepth)) { pickDepth = new PickDepth(); - scene._pickDepths[index] = pickDepth; + pickDepths[index] = pickDepth; } return pickDepth; } @@ -2136,7 +1899,7 @@ define([ var scratchOrthographicOffCenterFrustum = new OrthographicOffCenterFrustum(); function executeCommands(scene, passState) { - var camera = scene._camera; + var camera = scene.camera; var context = scene.context; var us = context.uniformState; @@ -2161,11 +1924,12 @@ define([ us.updateFrustum(frustum); us.updatePass(Pass.ENVIRONMENT); - var useWebVR = scene._useWebVR && scene.mode !== SceneMode.SCENE2D; var passes = scene._frameState.passes; var picking = passes.pick; - var depthOnly = passes.depth; var environmentState = scene._environmentState; + var view = scene._view; + var renderTranslucentDepthForPick = environmentState.renderTranslucentDepthForPick; + var useWebVR = environmentState.useWebVR; // Do not render environment primitives during a pick pass since they do not generate picking commands. if (!picking) { @@ -2183,9 +1947,9 @@ define([ if (scene.sunBloom && !useWebVR) { var framebuffer; if (environmentState.useGlobeDepthFramebuffer) { - framebuffer = scene._globeDepth.framebuffer; + framebuffer = view.globeDepth.framebuffer; } else if (environmentState.usePostProcess) { - framebuffer = scene._sceneFramebuffer.getFramebuffer(); + framebuffer = view.sceneFramebuffer.getFramebuffer(); } else { framebuffer = environmentState.originalFramebuffer; } @@ -2206,17 +1970,20 @@ define([ if (environmentState.useOIT) { if (!defined(scene._executeOITFunction)) { scene._executeOITFunction = function(scene, executeFunction, passState, commands, invertClassification) { - scene._oit.executeCommands(scene, executeFunction, passState, commands, invertClassification); + view.oit.executeCommands(scene, executeFunction, passState, commands, invertClassification); }; } executeTranslucentCommands = scene._executeOITFunction; - } else { + } else if (passes.render) { executeTranslucentCommands = executeTranslucentCommandsSorted; + } else { + executeTranslucentCommands = executeTranslucentCommandsUnsorted; } var clearGlobeDepth = environmentState.clearGlobeDepth; var useDepthPlane = environmentState.useDepthPlane; var clearDepth = scene._depthClearCommand; + var clearStencil = scene._stencilClearCommand; var depthPlane = scene._depthPlane; var usePostProcessSelected = environmentState.usePostProcessSelected; @@ -2224,7 +1991,7 @@ define([ // Execute commands in each frustum in back to front order var j; - var frustumCommandsList = scene._frustumCommandsList; + var frustumCommandsList = view.frustumCommandsList; var numFrustums = frustumCommandsList.length; for (var i = 0; i < numFrustums; ++i) { @@ -2246,18 +2013,21 @@ define([ us.updateFrustum(frustum); } - var globeDepth = scene.debugShowGlobeDepth ? getDebugGlobeDepth(scene, index) : scene._globeDepth; + var globeDepth = scene.debugShowGlobeDepth ? getDebugGlobeDepth(scene, index) : view.globeDepth; var fb; if (scene.debugShowGlobeDepth && defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { - globeDepth.update(context, passState); + globeDepth.update(context, passState, view.viewport); globeDepth.clear(context, passState, scene._clearColorCommand.color); fb = passState.framebuffer; passState.framebuffer = globeDepth.framebuffer; } clearDepth.execute(context, passState); - scene._stencilClearCommand.execute(context, passState); + + if (context.stencilBuffer) { + clearStencil.execute(context, passState); + } us.updatePass(Pass.GLOBE); var commands = frustumCommands.commands[Pass.GLOBE]; @@ -2267,7 +2037,7 @@ define([ } if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { - globeDepth.update(context, passState); + globeDepth.update(context, passState, view.viewport); globeDepth.executeCopyDepth(context, passState); } @@ -2386,7 +2156,7 @@ define([ // Clear stencil set by the classification for the next classification pass if (length > 0 && context.stencilBuffer) { - scene._stencilClearCommand.execute(context, passState); + clearStencil.execute(context, passState); } // Draw style over classification. @@ -2407,7 +2177,7 @@ define([ } if (length > 0 && context.stencilBuffer) { - scene._stencilClearCommand.execute(context, passState); + clearStencil.execute(context, passState); } if (clearGlobeDepth && useDepthPlane) { @@ -2439,9 +2209,9 @@ define([ commands.length = frustumCommands.indices[Pass.TRANSLUCENT]; executeTranslucentCommands(scene, executeCommand, passState, commands, invertClassification); - if (defined(globeDepth) && (environmentState.useGlobeDepthFramebuffer || depthOnly) && scene.useDepthPicking) { + if (context.depthTexture && scene.useDepthPicking && (environmentState.useGlobeDepthFramebuffer || renderTranslucentDepthForPick)) { // PERFORMANCE_IDEA: Use MRT to avoid the extra copy. - var depthStencilTexture = depthOnly ? passState.framebuffer.depthStencilTexture : globeDepth.framebuffer.depthStencilTexture; + var depthStencilTexture = renderTranslucentDepthForPick ? passState.framebuffer.depthStencilTexture : globeDepth.framebuffer.depthStencilTexture; var pickDepth = getPickDepth(scene, index); pickDepth.update(context, depthStencilTexture); pickDepth.executeCopyDepth(context, passState); @@ -2452,7 +2222,7 @@ define([ } var originalFramebuffer = passState.framebuffer; - passState.framebuffer = scene._sceneFramebuffer.getIdFramebuffer(); + passState.framebuffer = view.sceneFramebuffer.getIdFramebuffer(); // reset frustum frustum.near = index !== 0 ? frustumCommands.near * scene.opaqueFrustumNearOffset : frustumCommands.near; @@ -2538,10 +2308,10 @@ define([ var length = commandList.length; for (var i = 0; i < length; ++i) { var command = commandList[i]; - updateDerivedCommands(scene, command); + scene.updateDerivedCommands(command); if (command.castShadows && (command.pass === Pass.GLOBE || command.pass === Pass.CESIUM_3D_TILE || command.pass === Pass.OPAQUE || command.pass === Pass.TRANSLUCENT)) { - if (isVisible(command, shadowVolume)) { + if (scene.isVisible(command, shadowVolume)) { if (isPointLight) { for (var k = 0; k < numberOfPasses; ++k) { passes[k].commandList.push(command); @@ -2553,7 +2323,7 @@ define([ // Loop over cascades from largest to smallest for (var j = numberOfPasses - 1; j >= 0; --j) { var cascadeVolume = passes[j].cullingVolume; - if (isVisible(command, cascadeVolume)) { + if (scene.isVisible(command, cascadeVolume)) { passes[j].commandList.push(command); wasVisible = true; } else if (wasVisible) { @@ -2570,10 +2340,10 @@ define([ function executeShadowMapCastCommands(scene) { var frameState = scene.frameState; - var shadowMaps = frameState.shadowHints.shadowMaps; + var shadowMaps = frameState.shadowState.shadowMaps; var shadowMapLength = shadowMaps.length; - if (!frameState.shadowHints.shadowsEnabled) { + if (!frameState.shadowState.shadowsEnabled) { return; } @@ -2617,72 +2387,71 @@ define([ var scratchEyeTranslation = new Cartesian3(); function updateAndExecuteCommands(scene, passState, backgroundColor) { - var context = scene._context; - - var viewport = passState.viewport; - viewport.x = 0; - viewport.y = 0; - viewport.width = context.drawingBufferWidth; - viewport.height = context.drawingBufferHeight; - var frameState = scene._frameState; - var camera = frameState.camera; var mode = frameState.mode; - var depthOnly = frameState.passes.depth; + var useWebVR = scene._environmentState.useWebVR; - if (scene._useWebVR && mode !== SceneMode.SCENE2D) { + if (useWebVR) { + executeWebVRCommands(scene, passState, backgroundColor); + } else if (mode !== SceneMode.SCENE2D || scene._mapMode2D === MapMode2D.ROTATE) { + executeCommandsInViewport(true, scene, passState, backgroundColor); + } else { updateAndClearFramebuffers(scene, passState, backgroundColor); + execute2DViewportCommands(scene, passState); + } + } - if (!depthOnly) { - updateAndRenderPrimitives(scene); - } + function executeWebVRCommands(scene, passState, backgroundColor) { + var view = scene._view; + var camera = view.camera; + var environmentState = scene._environmentState; + var renderTranslucentDepthForPick = environmentState.renderTranslucentDepthForPick; - createPotentiallyVisibleSet(scene); + updateAndClearFramebuffers(scene, passState, backgroundColor); - if (!depthOnly) { - executeComputeCommands(scene); - executeShadowMapCastCommands(scene); - } + if (!renderTranslucentDepthForPick) { + updateAndRenderPrimitives(scene); + } + + view.createPotentiallyVisibleSet(scene); - // Based on Calculating Stereo pairs by Paul Bourke - // http://paulbourke.net/stereographics/stereorender/ + if (!renderTranslucentDepthForPick) { + executeComputeCommands(scene); + executeShadowMapCastCommands(scene); + } - viewport.x = 0; - viewport.y = 0; - viewport.width = context.drawingBufferWidth * 0.5; - viewport.height = context.drawingBufferHeight; + // Based on Calculating Stereo pairs by Paul Bourke + // http://paulbourke.net/stereographics/stereorender/ + var viewport = passState.viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = viewport.width * 0.5; - var savedCamera = Camera.clone(camera, scene._cameraVR); - savedCamera.frustum = camera.frustum; + var savedCamera = Camera.clone(camera, scene._cameraVR); + savedCamera.frustum = camera.frustum; - var near = camera.frustum.near; - var fo = near * defaultValue(scene.focalLength, 5.0); - var eyeSeparation = defaultValue(scene.eyeSeparation, fo / 30.0); - var eyeTranslation = Cartesian3.multiplyByScalar(savedCamera.right, eyeSeparation * 0.5, scratchEyeTranslation); + var near = camera.frustum.near; + var fo = near * defaultValue(scene.focalLength, 5.0); + var eyeSeparation = defaultValue(scene.eyeSeparation, fo / 30.0); + var eyeTranslation = Cartesian3.multiplyByScalar(savedCamera.right, eyeSeparation * 0.5, scratchEyeTranslation); - camera.frustum.aspectRatio = viewport.width / viewport.height; + camera.frustum.aspectRatio = viewport.width / viewport.height; - var offset = 0.5 * eyeSeparation * near / fo; + var offset = 0.5 * eyeSeparation * near / fo; - Cartesian3.add(savedCamera.position, eyeTranslation, camera.position); - camera.frustum.xOffset = offset; + Cartesian3.add(savedCamera.position, eyeTranslation, camera.position); + camera.frustum.xOffset = offset; - executeCommands(scene, passState); + executeCommands(scene, passState); - viewport.x = passState.viewport.width; + viewport.x = viewport.width; - Cartesian3.subtract(savedCamera.position, eyeTranslation, camera.position); - camera.frustum.xOffset = -offset; + Cartesian3.subtract(savedCamera.position, eyeTranslation, camera.position); + camera.frustum.xOffset = -offset; - executeCommands(scene, passState); + executeCommands(scene, passState); - Camera.clone(savedCamera, camera); - } else if (mode !== SceneMode.SCENE2D || scene._mapMode2D === MapMode2D.ROTATE) { - executeCommandsInViewport(true, scene, passState, backgroundColor); - } else { - updateAndClearFramebuffers(scene, passState, backgroundColor); - execute2DViewportCommands(scene, passState); - } + Camera.clone(savedCamera, camera); } var scratch2DViewportCartographic = new Cartographic(Math.PI, CesiumMath.PI_OVER_TWO); @@ -2808,23 +2577,25 @@ define([ } function executeCommandsInViewport(firstViewport, scene, passState, backgroundColor) { - var depthOnly = scene.frameState.passes.depth; + var environmentState = scene._environmentState; + var view = scene._view; + var renderTranslucentDepthForPick = environmentState.renderTranslucentDepthForPick; - if (!firstViewport && !depthOnly) { + if (!firstViewport && !renderTranslucentDepthForPick) { scene.frameState.commandList.length = 0; } - if (!depthOnly) { + if (!renderTranslucentDepthForPick) { updateAndRenderPrimitives(scene); } - createPotentiallyVisibleSet(scene); + view.createPotentiallyVisibleSet(scene); if (firstViewport) { if (defined(backgroundColor)) { updateAndClearFramebuffers(scene, passState, backgroundColor); } - if (!depthOnly) { + if (!renderTranslucentDepthForPick) { executeComputeCommands(scene); executeShadowMapCastCommands(scene); } @@ -2833,8 +2604,9 @@ define([ executeCommands(scene, passState); } - function updateEnvironment(scene, passState) { + function updateEnvironment(scene) { var frameState = scene._frameState; + var view = scene._view; // Update celestial and terrestrial environment effects. var environmentState = scene._environmentState; @@ -2842,7 +2614,7 @@ define([ var skyAtmosphere = scene.skyAtmosphere; var globe = scene.globe; - if (!renderPass || (scene._mode !== SceneMode.SCENE2D && frameState.camera.frustum instanceof OrthographicFrustum)) { + if (!renderPass || (scene._mode !== SceneMode.SCENE2D && view.camera.frustum instanceof OrthographicFrustum)) { environmentState.skyAtmosphereCommand = undefined; environmentState.skyBoxCommand = undefined; environmentState.sunDrawCommand = undefined; @@ -2855,7 +2627,7 @@ define([ } environmentState.skyAtmosphereCommand = defined(skyAtmosphere) ? skyAtmosphere.update(frameState) : undefined; environmentState.skyBoxCommand = defined(scene.skyBox) ? scene.skyBox.update(frameState) : undefined; - var sunCommands = defined(scene.sun) ? scene.sun.update(frameState, passState) : undefined; + var sunCommands = defined(scene.sun) ? scene.sun.update(frameState, view.passState) : undefined; environmentState.sunDrawCommand = defined(sunCommands) ? sunCommands.drawCommand : undefined; environmentState.sunComputeCommand = defined(sunCommands) ? sunCommands.computeCommand : undefined; environmentState.moonCommand = defined(scene.moon) ? scene.moon.update(frameState) : undefined; @@ -2864,13 +2636,15 @@ define([ var clearGlobeDepth = environmentState.clearGlobeDepth = defined(globe) && (!globe.depthTestAgainstTerrain || scene.mode === SceneMode.SCENE2D); var useDepthPlane = environmentState.useDepthPlane = clearGlobeDepth && scene.mode === SceneMode.SCENE3D; if (useDepthPlane) { - var useLogDepth = scene._logDepthBuffer && !(scene.camera.frustum instanceof OrthographicFrustum || scene.camera.frustum instanceof OrthographicOffCenterFrustum); // Update the depth plane that is rendered in 3D when the primitives are // not depth tested against terrain so primitives on the backface // of the globe are not picked. - scene._depthPlane.update(frameState, useLogDepth); + scene._depthPlane.update(frameState); } + environmentState.renderTranslucentDepthForPick = false; + environmentState.useWebVR = scene._useWebVR && scene.mode !== SceneMode.SCENE2D; + var occluder = (frameState.mode === SceneMode.SCENE3D) ? frameState.occluder: undefined; var cullingVolume = frameState.cullingVolume; @@ -2883,8 +2657,8 @@ define([ // Determine visibility of celestial and terrestrial environment effects. environmentState.isSkyAtmosphereVisible = defined(environmentState.skyAtmosphereCommand) && environmentState.isReadyForAtmosphere; - environmentState.isSunVisible = isVisible(environmentState.sunDrawCommand, cullingVolume, occluder); - environmentState.isMoonVisible = isVisible(environmentState.moonCommand, cullingVolume, occluder); + environmentState.isSunVisible = scene.isVisible(environmentState.sunDrawCommand, cullingVolume, occluder); + environmentState.isMoonVisible = scene.isVisible(environmentState.moonCommand, cullingVolume, occluder); } function updateDebugFrustumPlanes(scene) { @@ -2912,13 +2686,13 @@ define([ var length = shadowMaps.length; var shadowsEnabled = (length > 0) && !frameState.passes.pick && (scene.mode === SceneMode.SCENE3D); - if (shadowsEnabled !== frameState.shadowHints.shadowsEnabled) { + if (shadowsEnabled !== frameState.shadowState.shadowsEnabled) { // Update derived commands when shadowsEnabled changes - ++frameState.shadowHints.lastDirtyTime; - frameState.shadowHints.shadowsEnabled = shadowsEnabled; + ++frameState.shadowState.lastDirtyTime; + frameState.shadowState.shadowsEnabled = shadowsEnabled; } - frameState.shadowHints.lightShadowsEnabled = false; + frameState.shadowState.lightShadowsEnabled = false; if (!shadowsEnabled) { return; @@ -2927,28 +2701,28 @@ define([ // Check if the shadow maps are different than the shadow maps last frame. // If so, the derived commands need to be updated. for (var j = 0; j < length; ++j) { - if (shadowMaps[j] !== frameState.shadowHints.shadowMaps[j]) { - ++frameState.shadowHints.lastDirtyTime; + if (shadowMaps[j] !== frameState.shadowState.shadowMaps[j]) { + ++frameState.shadowState.lastDirtyTime; break; } } - frameState.shadowHints.shadowMaps.length = 0; - frameState.shadowHints.lightShadowMaps.length = 0; + frameState.shadowState.shadowMaps.length = 0; + frameState.shadowState.lightShadowMaps.length = 0; for (var i = 0; i < length; ++i) { var shadowMap = shadowMaps[i]; shadowMap.update(frameState); - frameState.shadowHints.shadowMaps.push(shadowMap); + frameState.shadowState.shadowMaps.push(shadowMap); if (shadowMap.fromLightSource) { - frameState.shadowHints.lightShadowMaps.push(shadowMap); - frameState.shadowHints.lightShadowsEnabled = true; + frameState.shadowState.lightShadowMaps.push(shadowMap); + frameState.shadowState.lightShadowsEnabled = true; } if (shadowMap.dirty) { - ++frameState.shadowHints.lastDirtyTime; + ++frameState.shadowState.lastDirtyTime; shadowMap.dirty = false; } } @@ -2970,11 +2744,13 @@ define([ function updateAndClearFramebuffers(scene, passState, clearColor) { var context = scene._context; + var frameState = scene._frameState; var environmentState = scene._environmentState; + var view = scene._view; var passes = scene._frameState.passes; var picking = passes.pick; - var useWebVR = scene._useWebVR && scene.mode !== SceneMode.SCENE2D; + var useWebVR = environmentState.useWebVR; // Preserve the reference to the original framebuffer. environmentState.originalFramebuffer = passState.framebuffer; @@ -2999,32 +2775,30 @@ define([ clear.execute(context, passState); // Update globe depth rendering based on the current context and clear the globe depth framebuffer. - // Globe depth needs is copied for Pick to support picking batched geometries in GroundPrimitives. - var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer = defined(scene._globeDepth); + // Globe depth is copied for the pick pass to support picking batched geometries in GroundPrimitives. + var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer = defined(view.globeDepth); if (useGlobeDepthFramebuffer) { - scene._globeDepth.update(context, passState); - scene._globeDepth.clear(context, passState, clearColor); + view.globeDepth.update(context, passState, view.viewport); + view.globeDepth.clear(context, passState, clearColor); } // If supported, configure OIT to use the globe depth framebuffer and clear the OIT framebuffer. - var useOIT = environmentState.useOIT = !picking && defined(scene._oit) && scene._oit.isSupported(); + var oit = view.oit; + var useOIT = environmentState.useOIT = !picking && defined(oit) && oit.isSupported(); if (useOIT) { - scene._oit.update(context, passState, scene._globeDepth.framebuffer); - scene._oit.clear(context, passState, clearColor); - environmentState.useOIT = scene._oit.isSupported(); + oit.update(context, passState, view.globeDepth.framebuffer); + oit.clear(context, passState, clearColor); + environmentState.useOIT = oit.isSupported(); } var postProcess = scene.postProcessStages; var usePostProcess = environmentState.usePostProcess = !picking && (postProcess.length > 0 || postProcess.ambientOcclusion.enabled || postProcess.fxaa.enabled || postProcess.bloom.enabled); environmentState.usePostProcessSelected = false; if (usePostProcess) { - scene._sceneFramebuffer.update(context, passState); - scene._sceneFramebuffer.clear(context, passState, clearColor); - - var camera = scene.camera; - var useLogDepth = scene._logDepthBuffer && !(camera.frustum instanceof OrthographicFrustum || camera.frustum instanceof OrthographicOffCenterFrustum); + view.sceneFramebuffer.update(context, view.viewport); + view.sceneFramebuffer.clear(context, passState, clearColor); - postProcess.update(context, useLogDepth); + postProcess.update(context, frameState.useLogDepth); postProcess.clear(context); usePostProcess = environmentState.usePostProcess = postProcess.ready; @@ -3035,9 +2809,9 @@ define([ passState.framebuffer = scene._sunPostProcess.update(passState); scene._sunPostProcess.clear(context, passState, clearColor); } else if (useGlobeDepthFramebuffer) { - passState.framebuffer = scene._globeDepth.framebuffer; + passState.framebuffer = view.globeDepth.framebuffer; } else if (usePostProcess) { - passState.framebuffer = scene._sceneFramebuffer.getFramebuffer(); + passState.framebuffer = view.sceneFramebuffer.getFramebuffer(); } if (defined(passState.framebuffer)) { @@ -3049,7 +2823,7 @@ define([ var depthFramebuffer; if (scene.frameState.invertClassificationColor.alpha === 1.0) { if (environmentState.useGlobeDepthFramebuffer) { - depthFramebuffer = scene._globeDepth.framebuffer; + depthFramebuffer = view.globeDepth.framebuffer; } } @@ -3061,7 +2835,7 @@ define([ if (scene.frameState.invertClassificationColor.alpha < 1.0 && useOIT) { var command = scene._invertClassification.unclassifiedCommand; var derivedCommands = command.derivedCommands; - derivedCommands.oit = scene._oit.createDerivedCommands(command, context, derivedCommands.oit); + derivedCommands.oit = oit.createDerivedCommands(command, context, derivedCommands.oit); } } else { environmentState.useInvertClassification = false; @@ -3071,20 +2845,22 @@ define([ function resolveFramebuffers(scene, passState) { var context = scene._context; + var frameState = scene._frameState; var environmentState = scene._environmentState; + var view = scene._view; var useOIT = environmentState.useOIT; var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer; var usePostProcess = environmentState.usePostProcess; var defaultFramebuffer = environmentState.originalFramebuffer; - var globeFramebuffer = useGlobeDepthFramebuffer ? scene._globeDepth.framebuffer : undefined; - var sceneFramebuffer = scene._sceneFramebuffer.getFramebuffer(); - var idFramebuffer = scene._sceneFramebuffer.getIdFramebuffer(); + var globeFramebuffer = useGlobeDepthFramebuffer ? view.globeDepth.framebuffer : undefined; + var sceneFramebuffer = view.sceneFramebuffer.getFramebuffer(); + var idFramebuffer = view.sceneFramebuffer.getIdFramebuffer(); if (useOIT) { passState.framebuffer = usePostProcess ? sceneFramebuffer : defaultFramebuffer; - scene._oit.execute(context, passState); + view.oit.execute(context, passState); } if (usePostProcess) { @@ -3103,11 +2879,10 @@ define([ if (!useOIT && !usePostProcess && useGlobeDepthFramebuffer) { passState.framebuffer = defaultFramebuffer; - scene._globeDepth.executeCopyColor(context, passState); + view.globeDepth.executeCopyColor(context, passState); } - var frustum = scene.camera.frustum; - var useLogDepth = scene._logDepthBuffer && !(frustum instanceof OrthographicFrustum || frustum instanceof OrthographicOffCenterFrustum); + var useLogDepth = frameState.useLogDepth; if (scene.debugShowGlobeDepth && useGlobeDepthFramebuffer) { var gd = getDebugGlobeDepth(scene, scene.debugShowDepthFrustum - 1); @@ -3149,35 +2924,10 @@ define([ this._deviceOrientationCameraController.update(); } - this._camera.update(this._mode); - this._camera._updateCameraChanged(); + this.camera.update(this._mode); + this.camera._updateCameraChanged(); }; - function checkForCameraUpdates(scene) { - var camera = scene._camera; - var cameraClone = scene._cameraClone; - - scene._frustumChanged = !camera.frustum.equals(cameraClone.frustum); - - if (!cameraEqual(camera, cameraClone, CesiumMath.EPSILON15)) { - if (!scene._cameraStartFired) { - camera.moveStart.raiseEvent(); - scene._cameraStartFired = true; - } - scene._cameraMovedTime = getTimestamp(); - Camera.clone(camera, cameraClone); - - return true; - } - - if (scene._cameraStartFired && getTimestamp() - scene._cameraMovedTime > scene.cameraEventWaitTime) { - camera.moveEnd.raiseEvent(); - scene._cameraStartFired = false; - } - - return false; - } - function updateDebugShowFramesPerSecond(scene, renderedThisFrame) { if (scene.debugShowFramesPerSecond) { if (!defined(scene._performanceDisplay)) { @@ -3215,6 +2965,9 @@ define([ var us = context.uniformState; var frameState = scene._frameState; + var view = scene._defaultView; + scene._view = view; + var frameNumber = CesiumMath.incrementWrap(frameState.frameNumber, 15000000.0, 1.0); updateFrameState(scene, frameNumber, time); frameState.passes.render = true; @@ -3239,16 +2992,23 @@ define([ scene._computeCommandList.length = 0; scene._overlayCommandList.length = 0; - var passState = scene._passState; + var viewport = view.viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = context.drawingBufferWidth; + viewport.height = context.drawingBufferHeight; + + var passState = view.passState; passState.framebuffer = undefined; passState.blendingEnabled = undefined; passState.scissorTest = undefined; + passState.viewport = BoundingRectangle.clone(viewport, passState.viewport); if (defined(scene.globe)) { scene.globe.beginFrame(frameState); } - updateEnvironment(scene, passState); + updateEnvironment(scene); updateAndExecuteCommands(scene, passState, backgroundColor); resolveFramebuffers(scene, passState); @@ -3297,7 +3057,7 @@ define([ tryAndCatchError(this, time, update); this._postUpdate.raiseEvent(this, time); - var cameraChanged = checkForCameraUpdates(this); + var cameraChanged = this._view.checkForCameraUpdates(this); var shouldRender = !this.requestRenderMode || this._renderRequested || cameraChanged || this._logDepthBufferDirty || (this.mode === SceneMode.MORPHING); if (!shouldRender && defined(this.maximumRenderTimeChange) && defined(this._lastRenderTime)) { var difference = Math.abs(JulianDate.secondsDifference(this._lastRenderTime, time)); @@ -3359,14 +3119,13 @@ define([ var scratchPixelSize = new Cartesian2(); var scratchPickVolumeMatrix4 = new Matrix4(); - function getPickOrthographicCullingVolume(scene, drawingBufferPosition, width, height) { - var camera = scene._camera; + function getPickOrthographicCullingVolume(scene, drawingBufferPosition, width, height, viewport) { + var camera = scene.camera; var frustum = camera.frustum; if (defined(frustum._offCenterFrustum)) { frustum = frustum._offCenterFrustum; } - var viewport = scene._passState.viewport; var x = 2.0 * (drawingBufferPosition.x - viewport.x) / viewport.width - 1.0; x *= (frustum.right - frustum.left) * 0.5; var y = 2.0 * (viewport.height - drawingBufferPosition.y - viewport.y) / viewport.height - 1.0; @@ -3402,15 +3161,14 @@ define([ var perspPickingFrustum = new PerspectiveOffCenterFrustum(); - function getPickPerspectiveCullingVolume(scene, drawingBufferPosition, width, height) { - var camera = scene._camera; + function getPickPerspectiveCullingVolume(scene, drawingBufferPosition, width, height, viewport) { + var camera = scene.camera; var frustum = camera.frustum; var near = frustum.near; var tanPhi = Math.tan(frustum.fovy * 0.5); var tanTheta = frustum.aspectRatio * tanPhi; - var viewport = scene._passState.viewport; var x = 2.0 * (drawingBufferPosition.x - viewport.x) / viewport.width - 1.0; var y = 2.0 * (viewport.height - drawingBufferPosition.y - viewport.y) / viewport.height - 1.0; @@ -3432,13 +3190,13 @@ define([ return offCenter.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC); } - function getPickCullingVolume(scene, drawingBufferPosition, width, height) { + function getPickCullingVolume(scene, drawingBufferPosition, width, height, viewport) { var frustum = scene.camera.frustum; if (frustum instanceof OrthographicFrustum || frustum instanceof OrthographicOffCenterFrustum) { - return getPickOrthographicCullingVolume(scene, drawingBufferPosition, width, height); + return getPickOrthographicCullingVolume(scene, drawingBufferPosition, width, height, viewport); } - return getPickPerspectiveCullingVolume(scene, drawingBufferPosition, width, height); + return getPickPerspectiveCullingVolume(scene, drawingBufferPosition, width, height, viewport); } // pick rectangle width and height, assumed odd @@ -3469,12 +3227,10 @@ define([ * @param {Number} [width=3] Width of the pick rectangle. * @param {Number} [height=3] Height of the pick rectangle. * @returns {Object} Object containing the picked primitive. - * - * @exception {DeveloperError} windowPosition is undefined. */ Scene.prototype.pick = function(windowPosition, width, height) { //>>includeStart('debug', pragmas.debug); - if(!defined(windowPosition)) { + if (!defined(windowPosition)) { throw new DeveloperError('windowPosition is undefined.'); } //>>includeEnd('debug'); @@ -3486,33 +3242,42 @@ define([ var us = context.uniformState; var frameState = this._frameState; - var drawingBufferPosition = SceneTransforms.transformWindowToDrawingBuffer(this, windowPosition, scratchPosition); + var view = this._defaultView; + this._view = view; - if (!defined(this._pickFramebuffer)) { - this._pickFramebuffer = context.createPickFramebuffer(); - } + var viewport = view.viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = context.drawingBufferWidth; + viewport.height = context.drawingBufferHeight; + + var passState = view.passState; + passState.viewport = BoundingRectangle.clone(viewport, passState.viewport); + + var drawingBufferPosition = SceneTransforms.transformWindowToDrawingBuffer(this, windowPosition, scratchPosition); this._jobScheduler.disableThisFrame(); // Update with previous frame's number and time, assuming that render is called before picking. updateFrameState(this, frameState.frameNumber, frameState.time); - frameState.cullingVolume = getPickCullingVolume(this, drawingBufferPosition, rectangleWidth, rectangleHeight); + frameState.cullingVolume = getPickCullingVolume(this, drawingBufferPosition, rectangleWidth, rectangleHeight, viewport); frameState.invertClassification = false; frameState.passes.pick = true; us.update(frameState); + updateEnvironment(this); + scratchRectangle.x = drawingBufferPosition.x - ((rectangleWidth - 1.0) * 0.5); scratchRectangle.y = (this.drawingBufferHeight - drawingBufferPosition.y) - ((rectangleHeight - 1.0) * 0.5); scratchRectangle.width = rectangleWidth; scratchRectangle.height = rectangleHeight; - var passState = this._pickFramebuffer.begin(scratchRectangle); + passState = view.pickFramebuffer.begin(scratchRectangle, view.viewport); - updateEnvironment(this, passState); updateAndExecuteCommands(this, passState, scratchColorZero); resolveFramebuffers(this, passState); - var object = this._pickFramebuffer.end(scratchRectangle); + var object = view.pickFramebuffer.end(scratchRectangle); context.endFrame(); callAfterRenderFunctions(this); return object; @@ -3522,63 +3287,35 @@ define([ // PERFORMANCE_IDEA: render translucent only and merge with the previous frame var context = scene._context; var frameState = scene._frameState; + var environmentState = scene._environmentState; + + var view = scene._defaultView; + scene._view = view; + + var viewport = view.viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = context.drawingBufferWidth; + viewport.height = context.drawingBufferHeight; + + var passState = view.passState; + passState.viewport = BoundingRectangle.clone(viewport, passState.viewport); clearPasses(frameState.passes); frameState.passes.pick = true; frameState.passes.depth = true; - frameState.cullingVolume = getPickCullingVolume(scene, drawingBufferPosition, 1, 1); - - var passState = scene._pickDepthPassState; - if (!defined(passState)) { - passState = scene._pickDepthPassState = new PassState(context); - passState.scissorTest = { - enabled : true, - rectangle : new BoundingRectangle() - }; - passState.viewport = new BoundingRectangle(); - } - - var width = context.drawingBufferWidth; - var height = context.drawingBufferHeight; - - var framebuffer = scene._pickDepthFramebuffer; - var pickDepthFBWidth = scene._pickDepthFramebufferWidth; - var pickDepthFBHeight = scene._pickDepthFramebufferHeight; - if (!defined(framebuffer) || pickDepthFBWidth !== width || pickDepthFBHeight !== height) { - scene._pickDepthFramebuffer = scene._pickDepthFramebuffer && scene._pickDepthFramebuffer.destroy(); - framebuffer = scene._pickDepthFramebuffer = new Framebuffer({ - context : context, - depthStencilTexture : new Texture({ - context : context, - width : width, - height : height, - pixelFormat : PixelFormat.DEPTH_STENCIL, - pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8 - }) - }); - - scene._pickDepthFramebufferWidth = width; - scene._pickDepthFramebufferHeight = height; - } + frameState.cullingVolume = getPickCullingVolume(scene, drawingBufferPosition, 1, 1, viewport); - passState.framebuffer = framebuffer; - passState.viewport.width = width; - passState.viewport.height = height; - passState.scissorTest.rectangle.x = drawingBufferPosition.x; - passState.scissorTest.rectangle.y = height - drawingBufferPosition.y; - passState.scissorTest.rectangle.width = 1; - passState.scissorTest.rectangle.height = 1; + updateEnvironment(scene); + environmentState.renderTranslucentDepthForPick = true; + passState = view.pickDepthFramebuffer.update(context, drawingBufferPosition, viewport); - updateEnvironment(scene, passState); updateAndExecuteCommands(scene, passState, scratchColorZero); resolveFramebuffers(scene, passState); context.endFrame(); } - var scratchPackedDepth = new Cartesian4(); - var packedDepthScale = new Cartesian4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0); - /** * Returns the cartesian position reconstructed from the depth buffer and window position. * The returned position is in world coordinates. Used internally by camera functions to @@ -3602,10 +3339,10 @@ define([ } //>>includeStart('debug', pragmas.debug); - if(!defined(windowPosition)) { + if (!defined(windowPosition)) { throw new DeveloperError('windowPosition is undefined.'); } - if (!defined(this._globeDepth)) { + if (!this._context.depthTexture) { throw new DeveloperError('Picking from the depth buffer is not supported. Check pickPositionSupported.'); } //>>includeEnd('debug'); @@ -3622,13 +3359,18 @@ define([ var context = this._context; var uniformState = context.uniformState; + var view = this._defaultView; + this._view = view; + var drawingBufferPosition = SceneTransforms.transformWindowToDrawingBuffer(this, windowPosition, scratchPosition); if (this.pickTranslucentDepth) { renderTranslucentDepthForPick(this, drawingBufferPosition); + } else { + updateEnvironment(this); } drawingBufferPosition.y = this.drawingBufferHeight - drawingBufferPosition.y; - var camera = this._camera; + var camera = this.camera; // Create a working frustum from the original camera frustum. var frustum; @@ -3642,23 +3384,13 @@ define([ frustum = camera.frustum.clone(scratchOrthographicOffCenterFrustum); } - var numFrustums = this.numberOfFrustums; + var frustumCommandsList = view.frustumCommandsList; + var numFrustums = frustumCommandsList.length; for (var i = 0; i < numFrustums; ++i) { var pickDepth = getPickDepth(this, i); - var pixels = context.readPixels({ - x : drawingBufferPosition.x, - y : drawingBufferPosition.y, - width : 1, - height : 1, - framebuffer : pickDepth.framebuffer - }); - - var packedDepth = Cartesian4.unpack(pixels, 0, scratchPackedDepth); - Cartesian4.divideByScalar(packedDepth, 255.0, packedDepth); - var depth = Cartesian4.dot(packedDepth, packedDepthScale); - + var depth = pickDepth.getDepth(context, drawingBufferPosition.x, drawingBufferPosition.y); if (depth > 0.0 && depth < 1.0) { - var renderedFrustum = this._frustumCommandsList[i]; + var renderedFrustum = frustumCommandsList[i]; var height2D; if (this.mode === SceneMode.SCENE2D) { height2D = camera.position.z; @@ -3760,6 +3492,7 @@ define([ var result = []; var pickedPrimitives = []; var pickedAttributes = []; + var pickedFeatures = []; if (!defined(limit)) { limit = Number.MAX_VALUE; } @@ -3786,7 +3519,13 @@ define([ } } - //Otherwise, hide the entire primitive + if (pickedResult instanceof Cesium3DTileFeature) { + hasShowAttribute = true; + pickedResult.show = false; + pickedFeatures.push(pickedResult); + } + + // Otherwise, hide the entire primitive if (!hasShowAttribute) { primitive.show = false; pickedPrimitives.push(primitive); @@ -3795,7 +3534,7 @@ define([ pickedResult = this.pick(windowPosition, width, height); } - // unhide everything we hid while drill picking + // Unhide everything we hid while drill picking for (i = 0; i < pickedPrimitives.length; ++i) { pickedPrimitives[i].show = true; } @@ -3805,6 +3544,10 @@ define([ attributes.show = ShowGeometryInstanceAttribute.toValue(true, attributes.show); } + for (i = 0; i < pickedFeatures.length; ++i) { + pickedFeatures[i].show = true; + } + return result; }; @@ -3920,8 +3663,6 @@ define([ this._computeEngine = this._computeEngine && this._computeEngine.destroy(); this._screenSpaceCameraController = this._screenSpaceCameraController && this._screenSpaceCameraController.destroy(); this._deviceOrientationCameraController = this._deviceOrientationCameraController && !this._deviceOrientationCameraController.isDestroyed() && this._deviceOrientationCameraController.destroy(); - this._pickFramebuffer = this._pickFramebuffer && this._pickFramebuffer.destroy(); - this._pickDepthFramebuffer = this._pickDepthFramebuffer && this._pickDepthFramebuffer.destroy(); this._primitives = this._primitives && this._primitives.destroy(); this._groundPrimitives = this._groundPrimitives && this._groundPrimitives.destroy(); this._globe = this._globe && this._globe.destroy(); @@ -3934,14 +3675,14 @@ define([ this._transitioner = this._transitioner && this._transitioner.destroy(); this._debugFrustumPlanes = this._debugFrustumPlanes && this._debugFrustumPlanes.destroy(); this._brdfLutGenerator = this._brdfLutGenerator && this._brdfLutGenerator.destroy(); - this._globeDepth = this._globeDepth && this._globeDepth.destroy(); - this._oit = this._oit && this._oit.destroy(); + + this._defaultView = this._defaultView && this._defaultView.destroy(); + this._view = undefined; if (this._removeCreditContainer) { this._canvas.parentNode.removeChild(this._creditContainer); } - this._sceneFramebuffer = this._sceneFramebuffer && this._sceneFramebuffer.destroy(); this.postProcessStages = this.postProcessStages && this.postProcessStages.destroy(); this._context = this._context && this._context.destroy(); diff --git a/Source/Scene/SceneFramebuffer.js b/Source/Scene/SceneFramebuffer.js index 7fc17a131e36..fe8c29116555 100644 --- a/Source/Scene/SceneFramebuffer.js +++ b/Source/Scene/SceneFramebuffer.js @@ -71,9 +71,9 @@ define([ post._depthStencilIdRenderbuffer = undefined; } - SceneFramebuffer.prototype.update = function(context) { - var width = context.drawingBufferWidth; - var height = context.drawingBufferHeight; + SceneFramebuffer.prototype.update = function(context, viewport) { + var width = viewport.width; + var height = viewport.height; var colorTexture = this._colorTexture; if (defined(colorTexture) && colorTexture.width === width && colorTexture.height === height) { return; diff --git a/Source/Scene/SceneTransforms.js b/Source/Scene/SceneTransforms.js index 96c32e4f738c..c9ec64266c3a 100644 --- a/Source/Scene/SceneTransforms.js +++ b/Source/Scene/SceneTransforms.js @@ -306,7 +306,7 @@ define([ var near = currentFrustum.x; var far = currentFrustum.y; - if (scene._logDepthBuffer && !(scene.camera.frustum instanceof OrthographicFrustum || scene.camera.frustum instanceof OrthographicOffCenterFrustum)) { + if (scene.frameState.useLogDepth) { // transforming logarithmic depth of form // log2(z + 1) / log2( far + 1); // to perspective form @@ -315,7 +315,7 @@ define([ depth = far * (1.0 - near / depth) / (far - near); } - var viewport = scene._passState.viewport; + var viewport = scene._view.passState.viewport; var ndc = Cartesian4.clone(Cartesian4.UNIT_W, scratchNDC); ndc.x = (drawingBufferPosition.x - viewport.x) / viewport.width * 2.0 - 1.0; ndc.y = (drawingBufferPosition.y - viewport.y) / viewport.height * 2.0 - 1.0; diff --git a/Source/Scene/SceneTransitioner.js b/Source/Scene/SceneTransitioner.js index 52d8e934eee8..36660944c54b 100644 --- a/Source/Scene/SceneTransitioner.js +++ b/Source/Scene/SceneTransitioner.js @@ -838,7 +838,7 @@ define([ } var frustum = camera.frustum; - if (scene._logDepthBuffer && !(frustum instanceof OrthographicFrustum || frustum instanceof OrthographicOffCenterFrustum)) { + if (scene.frameState.useLogDepth) { frustum.near = 0.1; frustum.far = 10000000000.0; } @@ -895,7 +895,7 @@ define([ } var frustum = camera.frustum; - if (scene._logDepthBuffer && !(frustum instanceof OrthographicFrustum || frustum instanceof OrthographicOffCenterFrustum)) { + if (scene.frameState.useLogDepth) { frustum.near = 0.1; frustum.far = 10000000000.0; } diff --git a/Source/Scene/ShadowMap.js b/Source/Scene/ShadowMap.js index 217ebca7b0cc..d8fa87a3a23c 100644 --- a/Source/Scene/ShadowMap.js +++ b/Source/Scene/ShadowMap.js @@ -1024,7 +1024,7 @@ define([ // When the camera is close to a relatively small model, provide more detail in the closer cascades. // If the camera is near or inside a large model, such as the root tile of a city, then use the default values. // To get the most accurate cascade splits we would need to find the min and max values from the depth texture. - if (frameState.shadowHints.closestObjectSize < 200.0) { + if (frameState.shadowState.closestObjectSize < 200.0) { clampCascadeDistances = true; lambda = 0.9; } @@ -1338,8 +1338,8 @@ define([ if (shadowMap._fitNearFar) { // shadowFar can be very large, so limit to shadowMap.maximumDistance // Push the far plane slightly further than the near plane to avoid degenerate frustum - near = Math.min(frameState.shadowHints.nearPlane, shadowMap.maximumDistance); - far = Math.min(frameState.shadowHints.farPlane, shadowMap.maximumDistance + 1.0); + near = Math.min(frameState.shadowState.nearPlane, shadowMap.maximumDistance); + far = Math.min(frameState.shadowState.farPlane, shadowMap.maximumDistance + 1.0); } else { near = camera.frustum.near; far = shadowMap.maximumDistance; @@ -1528,7 +1528,7 @@ define([ return result; } - ShadowMap.createDerivedCommands = function(shadowMaps, lightShadowMaps, command, shadowsDirty, context, result) { + ShadowMap.createReceiveDerivedCommand = function(lightShadowMaps, command, shadowsDirty, context, result) { if (!defined(result)) { result = {}; } @@ -1544,24 +1544,6 @@ define([ hasTerrainNormal = command.owner.data.pickTerrain.mesh.encoding.hasVertexNormals; } - if (command.castShadows) { - var castCommands = result.castCommands; - if (!defined(castCommands)) { - castCommands = result.castCommands = []; - } - - var oldShaderId = result.castShaderProgramId; - - var shadowMapLength = shadowMaps.length; - castCommands.length = shadowMapLength; - - for (var i = 0; i < shadowMapLength; ++i) { - castCommands[i] = createCastDerivedCommand(shadowMaps[i], shadowsDirty, command, context, oldShaderId, castCommands[i]); - } - - result.castShaderProgramId = command.shaderProgram.id; - } - if (command.receiveShadows && lightShadowMapsEnabled) { // Only generate a receiveCommand if there is a shadow map originating from a light source. var receiveShader; @@ -1606,6 +1588,32 @@ define([ return result; }; + ShadowMap.createCastDerivedCommand = function(shadowMaps, command, shadowsDirty, context, result) { + if (!defined(result)) { + result = {}; + } + + if (command.castShadows) { + var castCommands = result.castCommands; + if (!defined(castCommands)) { + castCommands = result.castCommands = []; + } + + var oldShaderId = result.castShaderProgramId; + + var shadowMapLength = shadowMaps.length; + castCommands.length = shadowMapLength; + + for (var i = 0; i < shadowMapLength; ++i) { + castCommands[i] = createCastDerivedCommand(shadowMaps[i], shadowsDirty, command, context, oldShaderId, castCommands[i]); + } + + result.castShaderProgramId = command.shaderProgram.id; + } + + return result; + }; + /** * @private */ diff --git a/Source/Scene/ShadowMapShader.js b/Source/Scene/ShadowMapShader.js index 6b04939e652f..74bb6cc01c34 100644 --- a/Source/Scene/ShadowMapShader.js +++ b/Source/Scene/ShadowMapShader.js @@ -20,7 +20,7 @@ define([ var defines = vs.defines.slice(0); var sources = vs.sources.slice(0); - vs.defines.push('SHADOW_MAP'); + defines.push('SHADOW_MAP'); if (isTerrain) { defines.push('GENERATE_POSITION'); @@ -132,7 +132,7 @@ define([ var defines = vs.defines.slice(0); var sources = vs.sources.slice(0); - vs.defines.push('SHADOW_MAP'); + defines.push('SHADOW_MAP'); if (isTerrain) { if (hasTerrainNormal) { diff --git a/Source/Scene/SunPostProcess.js b/Source/Scene/SunPostProcess.js index 477a7faafb92..fa0d8c8655d4 100644 --- a/Source/Scene/SunPostProcess.js +++ b/Source/Scene/SunPostProcess.js @@ -221,15 +221,15 @@ define([ SunPostProcess.prototype.update = function(passState) { var context = passState.context; + var viewport = passState.viewport; var sceneFramebuffer = this._sceneFramebuffer; - sceneFramebuffer.update(context); + sceneFramebuffer.update(context, viewport); var framebuffer = sceneFramebuffer.getFramebuffer(); this._textureCache.update(context); - this._stages.update(context); + this._stages.update(context, false); - var viewport = passState.viewport; updateSunPosition(this, context, viewport); return framebuffer; diff --git a/Source/Scene/Vector3DTilePrimitive.js b/Source/Scene/Vector3DTilePrimitive.js index 91cee93c9a62..41459814c3a5 100644 --- a/Source/Scene/Vector3DTilePrimitive.js +++ b/Source/Scene/Vector3DTilePrimitive.js @@ -819,7 +819,8 @@ define([ var stencilPreloadCommand = pickCommands[j * 3]; if (!defined(stencilPreloadCommand)) { stencilPreloadCommand = pickCommands[j * 3] = new DrawCommand({ - owner : primitive + owner : primitive, + pickOnly : true }); } @@ -835,7 +836,8 @@ define([ var stencilDepthCommand = pickCommands[j * 3 + 1]; if (!defined(stencilDepthCommand)) { stencilDepthCommand = pickCommands[j * 3 + 1] = new DrawCommand({ - owner : primitive + owner : primitive, + pickOnly : true }); } @@ -851,7 +853,8 @@ define([ var colorCommand = pickCommands[j * 3 + 2]; if (!defined(colorCommand)) { colorCommand = pickCommands[j * 3 + 2] = new DrawCommand({ - owner : primitive + owner : primitive, + pickOnly : true }); } diff --git a/Source/Scene/View.js b/Source/Scene/View.js new file mode 100644 index 000000000000..2a4fcac0d75b --- /dev/null +++ b/Source/Scene/View.js @@ -0,0 +1,401 @@ +define([ + '../Core/BoundingRectangle', + '../Core/Cartesian3', + '../Core/CullingVolume', + '../Core/defined', + '../Core/getTimestamp', + '../Core/Interval', + '../Core/Math', + '../Core/Matrix4', + '../Core/OrthographicFrustum', + '../Core/OrthographicOffCenterFrustum', + '../Renderer/ClearCommand', + '../Renderer/Pass', + '../Renderer/PassState', + './Camera', + './FrustumCommands', + './GlobeDepth', + './OIT', + './PickDepthFramebuffer', + './PickFramebuffer', + './SceneFramebuffer', + './SceneMode', + './ShadowMap' + ], function( + BoundingRectangle, + Cartesian3, + CullingVolume, + defined, + getTimestamp, + Interval, + CesiumMath, + Matrix4, + OrthographicFrustum, + OrthographicOffCenterFrustum, + ClearCommand, + Pass, + PassState, + Camera, + FrustumCommands, + GlobeDepth, + OIT, + PickDepthFramebuffer, + PickFramebuffer, + SceneFramebuffer, + SceneMode, + ShadowMap) { + 'use strict'; + + /** + * @private + */ + function View(scene, camera, viewport) { + var context = scene.context; + + var frustumCommandsList = []; + + // Initial guess at frustums. + var near = camera.frustum.near; + var far = camera.frustum.far; + var farToNearRatio = scene.logarithmicDepthBuffer ? scene.logarithmicDepthFarToNearRatio : scene.farToNearRatio; + + var numFrustums = Math.ceil(Math.log(far / near) / Math.log(farToNearRatio)); + updateFrustums(near, far, farToNearRatio, numFrustums, scene.logarithmicDepthBuffer, frustumCommandsList, false, undefined, false, undefined); + + var globeDepth; + if (context.depthTexture) { + globeDepth = new GlobeDepth(); + } + + var oit; + if (scene._useOIT && context.depthTexture) { + oit = new OIT(context); + } + + var passState = new PassState(context); + passState.viewport = BoundingRectangle.clone(viewport); + + this.camera = camera; + this._cameraClone = Camera.clone(camera); + this._cameraStartFired = false; + this._cameraMovedTime = undefined; + + this.viewport = viewport; + this.passState = passState; + this.pickFramebuffer = new PickFramebuffer(context); + this.pickDepthFramebuffer = new PickDepthFramebuffer(); + this.sceneFramebuffer = new SceneFramebuffer(); + this.globeDepth = globeDepth; + this.oit = oit; + this.pickDepths = []; + this.debugGlobeDepths = []; + this.frustumCommandsList = frustumCommandsList; + this.debugFrustumStatistics = undefined; + this.updateFrustums = false; + } + + var scratchPosition0 = new Cartesian3(); + var scratchPosition1 = new Cartesian3(); + function maxComponent(a, b) { + var x = Math.max(Math.abs(a.x), Math.abs(b.x)); + var y = Math.max(Math.abs(a.y), Math.abs(b.y)); + var z = Math.max(Math.abs(a.z), Math.abs(b.z)); + return Math.max(Math.max(x, y), z); + } + + function cameraEqual(camera0, camera1, epsilon) { + var scalar = 1 / Math.max(1, maxComponent(camera0.position, camera1.position)); + Cartesian3.multiplyByScalar(camera0.position, scalar, scratchPosition0); + Cartesian3.multiplyByScalar(camera1.position, scalar, scratchPosition1); + return Cartesian3.equalsEpsilon(scratchPosition0, scratchPosition1, epsilon) && + Cartesian3.equalsEpsilon(camera0.direction, camera1.direction, epsilon) && + Cartesian3.equalsEpsilon(camera0.up, camera1.up, epsilon) && + Cartesian3.equalsEpsilon(camera0.right, camera1.right, epsilon) && + Matrix4.equalsEpsilon(camera0.transform, camera1.transform, epsilon) && + camera0.frustum.equalsEpsilon(camera1.frustum, epsilon); + } + + View.prototype.checkForCameraUpdates = function(scene) { + var camera = this.camera; + var cameraClone = this._cameraClone; + if (!cameraEqual(camera, cameraClone, CesiumMath.EPSILON15)) { + if (!this._cameraStartFired) { + camera.moveStart.raiseEvent(); + this._cameraStartFired = true; + } + this._cameraMovedTime = getTimestamp(); + Camera.clone(camera, cameraClone); + + return true; + } + + if (this._cameraStartFired && getTimestamp() - this._cameraMovedTime > scene.cameraEventWaitTime) { + camera.moveEnd.raiseEvent(); + this._cameraStartFired = false; + } + + return false; + }; + + function updateFrustums(near, far, farToNearRatio, numFrustums, logDepth, frustumCommandsList, is2D, nearToFarDistance2D, isOrthographic, nearToFarDistanceOrthographic) { + frustumCommandsList.length = numFrustums; + for (var m = 0; m < numFrustums; ++m) { + var curNear; + var curFar; + + if (is2D) { + curNear = Math.min(far - nearToFarDistance2D, near + m * nearToFarDistance2D); + curFar = Math.min(far, curNear + nearToFarDistance2D); + } else if (isOrthographic) { + curNear = near + nearToFarDistanceOrthographic * m; + curFar = Math.min(far, curNear + nearToFarDistanceOrthographic); + } else { + curNear = Math.max(near, Math.pow(farToNearRatio, m) * near); + curFar = farToNearRatio * curNear; + if (!logDepth) { + curFar = Math.min(far, curFar); + } + } + + var frustumCommands = frustumCommandsList[m]; + if (!defined(frustumCommands)) { + frustumCommands = frustumCommandsList[m] = new FrustumCommands(curNear, curFar); + } else { + frustumCommands.near = curNear; + frustumCommands.far = curFar; + } + } + } + + function insertIntoBin(scene, view, command, distance) { + if (scene.debugShowFrustums) { + command.debugOverlappingFrustums = 0; + } + + var frustumCommandsList = view.frustumCommandsList; + var length = frustumCommandsList.length; + + for (var i = 0; i < length; ++i) { + var frustumCommands = frustumCommandsList[i]; + var curNear = frustumCommands.near; + var curFar = frustumCommands.far; + + if (distance.start > curFar) { + continue; + } + + if (distance.stop < curNear) { + break; + } + + var pass = command.pass; + var index = frustumCommands.indices[pass]++; + frustumCommands.commands[pass][index] = command; + + if (scene.debugShowFrustums) { + command.debugOverlappingFrustums |= (1 << i); + } + + if (command.executeInClosestFrustum) { + break; + } + } + + if (scene.debugShowFrustums) { + var cf = view.debugFrustumStatistics.commandsInFrustums; + cf[command.debugOverlappingFrustums] = defined(cf[command.debugOverlappingFrustums]) ? cf[command.debugOverlappingFrustums] + 1 : 1; + ++view.debugFrustumStatistics.totalCommands; + } + + scene.updateDerivedCommands(command); + } + + var scratchCullingVolume = new CullingVolume(); + var distances = new Interval(); + + View.prototype.createPotentiallyVisibleSet = function(scene) { + var frameState = scene.frameState; + var camera = frameState.camera; + var direction = camera.directionWC; + var position = camera.positionWC; + + var computeList = scene._computeCommandList; + var overlayList = scene._overlayCommandList; + var commandList = frameState.commandList; + + if (scene.debugShowFrustums) { + this.debugFrustumStatistics = { + totalCommands : 0, + commandsInFrustums : {} + }; + } + + var frustumCommandsList = this.frustumCommandsList; + var numberOfFrustums = frustumCommandsList.length; + var numberOfPasses = Pass.NUMBER_OF_PASSES; + for (var n = 0; n < numberOfFrustums; ++n) { + for (var p = 0; p < numberOfPasses; ++p) { + frustumCommandsList[n].indices[p] = 0; + } + } + + computeList.length = 0; + overlayList.length = 0; + + var near = Number.MAX_VALUE; + var far = -Number.MAX_VALUE; + var undefBV = false; + + var shadowsEnabled = frameState.shadowState.shadowsEnabled; + var shadowNear = Number.MAX_VALUE; + var shadowFar = -Number.MAX_VALUE; + var shadowClosestObjectSize = Number.MAX_VALUE; + + var occluder = (frameState.mode === SceneMode.SCENE3D) ? frameState.occluder: undefined; + var cullingVolume = frameState.cullingVolume; + + // get user culling volume minus the far plane. + var planes = scratchCullingVolume.planes; + for (var k = 0; k < 5; ++k) { + planes[k] = cullingVolume.planes[k]; + } + cullingVolume = scratchCullingVolume; + + var length = commandList.length; + for (var i = 0; i < length; ++i) { + var command = commandList[i]; + var pass = command.pass; + + if (pass === Pass.COMPUTE) { + computeList.push(command); + } else if (pass === Pass.OVERLAY) { + overlayList.push(command); + } else { + var boundingVolume = command.boundingVolume; + if (defined(boundingVolume)) { + if (!scene.isVisible(command, cullingVolume, occluder)) { + continue; + } + + distances = boundingVolume.computePlaneDistances(position, direction, distances); + near = Math.min(near, distances.start); + far = Math.max(far, distances.stop); + + // Compute a tight near and far plane for commands that receive shadows. This helps compute + // good splits for cascaded shadow maps. Ignore commands that exceed the maximum distance. + // When moving the camera low LOD globe tiles begin to load, whose bounding volumes + // throw off the near/far fitting for the shadow map. Only update for globe tiles that the + // camera isn't inside. + if (shadowsEnabled && command.receiveShadows && (distances.start < ShadowMap.MAXIMUM_DISTANCE) && + !((pass === Pass.GLOBE) && (distances.start < -100.0) && (distances.stop > 100.0))) { + + // Get the smallest bounding volume the camera is near. This is used to place more shadow detail near the object. + var size = distances.stop - distances.start; + if ((pass !== Pass.GLOBE) && (distances.start < 100.0)) { + shadowClosestObjectSize = Math.min(shadowClosestObjectSize, size); + } + shadowNear = Math.min(shadowNear, distances.start); + shadowFar = Math.max(shadowFar, distances.stop); + } + } else { + // Clear commands don't need a bounding volume - just add the clear to all frustums. + // If another command has no bounding volume, though, we need to use the camera's + // worst-case near and far planes to avoid clipping something important. + distances.start = camera.frustum.near; + distances.stop = camera.frustum.far; + undefBV = !(command instanceof ClearCommand); + } + + insertIntoBin(scene, this, command, distances); + } + } + + if (undefBV) { + near = camera.frustum.near; + far = camera.frustum.far; + } else { + // The computed near plane must be between the user defined near and far planes. + // The computed far plane must between the user defined far and computed near. + // This will handle the case where the computed near plane is further than the user defined far plane. + near = Math.min(Math.max(near, camera.frustum.near), camera.frustum.far); + far = Math.max(Math.min(far, camera.frustum.far), near); + + if (shadowsEnabled) { + shadowNear = Math.min(Math.max(shadowNear, camera.frustum.near), camera.frustum.far); + shadowFar = Math.max(Math.min(shadowFar, camera.frustum.far), shadowNear); + } + } + + // Use the computed near and far for shadows + if (shadowsEnabled) { + frameState.shadowState.nearPlane = shadowNear; + frameState.shadowState.farPlane = shadowFar; + frameState.shadowState.closestObjectSize = shadowClosestObjectSize; + } + + // Exploit temporal coherence. If the frustums haven't changed much, use the frustums computed + // last frame, else compute the new frustums and sort them by frustum again. + var is2D = scene.mode === SceneMode.SCENE2D; + var isOrthographic = (scene.camera.frustum instanceof OrthographicFrustum || scene.camera.frustum instanceof OrthographicOffCenterFrustum); + var logDepth = frameState.useLogDepth; + var farToNearRatio = logDepth ? scene.logarithmicDepthFarToNearRatio : scene.farToNearRatio; + var numFrustums; + + if (is2D) { + // The multifrustum for 2D is uniformly distributed. To avoid z-fighting in 2D, + // the camera is moved to just before the frustum and the frustum depth is scaled + // to be in [1.0, nearToFarDistance2D]. + far = Math.min(far, camera.position.z + scene.nearToFarDistance2D); + near = Math.min(near, far); + numFrustums = Math.ceil(Math.max(1.0, far - near) / scene.nearToFarDistance2D); + } else if (isOrthographic) { + // The multifrustum for orthographic is uniformly distributed. + numFrustums = Math.ceil(Math.max(1.0, far - near) / scene.nearToFarDistanceOrthographic); + } else { + // The multifrustum for 3D/CV is non-uniformly distributed. + numFrustums = Math.ceil(Math.log(far / near) / Math.log(farToNearRatio)); + } + + if (this.updateFrustums || (near !== Number.MAX_VALUE && (numFrustums !== numberOfFrustums || (frustumCommandsList.length !== 0 && + (near < frustumCommandsList[0].near || (far > frustumCommandsList[numberOfFrustums - 1].far && (logDepth || !CesiumMath.equalsEpsilon(far, frustumCommandsList[numberOfFrustums - 1].far, CesiumMath.EPSILON8)))))))) { + this.updateFrustums = false; + updateFrustums(near, far, farToNearRatio, numFrustums, logDepth, frustumCommandsList, is2D, scene.nearToFarDistance2D, isOrthographic, scene.nearToFarDistanceOrthographic); + this.createPotentiallyVisibleSet(scene); + } + + var frustumSplits = frameState.frustumSplits; + frustumSplits.length = numFrustums + 1; + for (var j = 0; j < numFrustums; ++j) { + frustumSplits[j] = frustumCommandsList[j].near; + if (j === numFrustums - 1) { + frustumSplits[j + 1] = frustumCommandsList[j].far; + } + } + }; + + View.prototype.destroy = function() { + this.pickFramebuffer = this.pickFramebuffer && this.pickFramebuffer.destroy(); + this.pickDepthFramebuffer = this.pickDepthFramebuffer && this.pickDepthFramebuffer.destroy(); + this.sceneFramebuffer = this.sceneFramebuffer && this.sceneFramebuffer.destroy(); + this.globeDepth = this.globeDepth && this.globeDepth.destroy(); + this.oit = this.oit && this.oit.destroy(); + + var i; + var length; + + var pickDepths = this.pickDepths; + var debugGlobeDepths = this.debugGlobeDepths; + + length = pickDepths.length; + for (i = 0; i < length; ++i) { + pickDepths[i].destroy(); + } + + length = debugGlobeDepths.length; + for (i = 0; i < length; ++i) { + debugGlobeDepths[i].destroy(); + } + }; + + return View; +}); diff --git a/Specs/Scene/ClippingPlaneCollectionSpec.js b/Specs/Scene/ClippingPlaneCollectionSpec.js index dc8a6c66fa32..c801d081bc6d 100644 --- a/Specs/Scene/ClippingPlaneCollectionSpec.js +++ b/Specs/Scene/ClippingPlaneCollectionSpec.js @@ -367,7 +367,7 @@ defineSuite([ it('update creates a float texture with no filtering or wrapping to house packed clipping planes', function() { var scene = createScene(); - if (!ClippingPlaneCollection.useFloatTexture(scene._context)) { + if (!ClippingPlaneCollection.useFloatTexture(scene.context)) { // Don't fail just because float textures aren't supported scene.destroyForSpecs(); return; @@ -402,7 +402,7 @@ defineSuite([ it('update fills the clipping plane texture with packed planes', function() { var scene = createScene(); - if (!ClippingPlaneCollection.useFloatTexture(scene._context)) { + if (!ClippingPlaneCollection.useFloatTexture(scene.context)) { // Don't fail just because float textures aren't supported scene.destroyForSpecs(); return; @@ -444,7 +444,7 @@ defineSuite([ it('reallocates textures when above capacity or below 1/4 capacity', function() { var scene = createScene(); - if (!ClippingPlaneCollection.useFloatTexture(scene._context)) { + if (!ClippingPlaneCollection.useFloatTexture(scene.context)) { // Don't fail just because float textures aren't supported scene.destroyForSpecs(); return; @@ -502,7 +502,7 @@ defineSuite([ it('performs partial updates when only a single plane has changed and full texture updates otherwise', function() { var scene = createScene(); - if (!ClippingPlaneCollection.useFloatTexture(scene._context)) { + if (!ClippingPlaneCollection.useFloatTexture(scene.context)) { // Don't fail just because float textures aren't supported scene.destroyForSpecs(); return; diff --git a/Specs/Scene/ModelInstanceCollectionSpec.js b/Specs/Scene/ModelInstanceCollectionSpec.js index df0f831a67e6..382d376f9ec3 100644 --- a/Specs/Scene/ModelInstanceCollectionSpec.js +++ b/Specs/Scene/ModelInstanceCollectionSpec.js @@ -517,10 +517,10 @@ defineSuite([ cull : true }).then(function(collection) { scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).not.toEqual(0); + expect(scene.frustumCommandsList.length).not.toEqual(0); scene.camera.lookAt(new Cartesian3(100000.0, 0.0, 0.0), new HeadingPitchRange(0.0, 0.0, 10.0)); scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).toEqual(0); + expect(scene.frustumCommandsList.length).toEqual(0); }); }); @@ -531,10 +531,10 @@ defineSuite([ cull : false }).then(function(collection) { scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).not.toEqual(0); + expect(scene.frustumCommandsList.length).not.toEqual(0); scene.camera.lookAt(new Cartesian3(100000.0, 0.0, 0.0), new HeadingPitchRange(0.0, 0.0, 10.0)); scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).not.toEqual(0); + expect(scene.frustumCommandsList.length).not.toEqual(0); }); }); diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index eb7de575bdf7..62d066ffbf7f 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -2607,12 +2607,12 @@ defineSuite([ // Look at the model m.zoomTo(); scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).not.toEqual(0); + expect(scene.frustumCommandsList.length).not.toEqual(0); // Move the model out of view m.modelMatrix = Matrix4.fromTranslation(new Cartesian3(100000.0, 0.0, 0.0)); scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).toEqual(0); + expect(scene.frustumCommandsList.length).toEqual(0); m.show = false; primitives.remove(m); @@ -2629,12 +2629,12 @@ defineSuite([ // Look at the model m.zoomTo(); scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).not.toEqual(0); + expect(scene.frustumCommandsList.length).not.toEqual(0); // Move the model out of view m.modelMatrix = Matrix4.fromTranslation(new Cartesian3(10000000000.0, 0.0, 0.0)); scene.renderForSpecs(); - expect(scene._frustumCommandsList.length).not.toEqual(0); + expect(scene.frustumCommandsList.length).not.toEqual(0); m.show = false; primitives.remove(m); diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index 2bb926965d0d..692536eab401 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -367,10 +367,10 @@ defineSuite([ createBillboards(); scene.render(); - expect(scene._frustumCommandsList.length).toEqual(3); + expect(scene.frustumCommandsList.length).toEqual(3); scene.logarithmicDepthBuffer = true; scene.render(); - expect(scene._frustumCommandsList.length).toEqual(1); + expect(scene.frustumCommandsList.length).toEqual(1); }); }, 'WebGL'); diff --git a/Specs/Scene/PointCloud3DTileContentSpec.js b/Specs/Scene/PointCloud3DTileContentSpec.js index 6197cf410e64..80d5100f715e 100644 --- a/Specs/Scene/PointCloud3DTileContentSpec.js +++ b/Specs/Scene/PointCloud3DTileContentSpec.js @@ -995,7 +995,7 @@ defineSuite([ }); it('clipping planes union regions (Float)', function() { - if (!ClippingPlaneCollection.useFloatTexture(scene._context)) { + if (!ClippingPlaneCollection.useFloatTexture(scene.context)) { // This configuration for the test fails in uint8 mode due to the small context return; } diff --git a/Specs/Scene/PolylineCollectionSpec.js b/Specs/Scene/PolylineCollectionSpec.js index dfd311ab0030..195fef56704c 100644 --- a/Specs/Scene/PolylineCollectionSpec.js +++ b/Specs/Scene/PolylineCollectionSpec.js @@ -41,7 +41,7 @@ defineSuite([ beforeEach(function() { polylines = new PolylineCollection(); scene.mode = SceneMode.SCENE3D; - scene._camera = new Camera(scene); + scene.camera = new Camera(scene); }); afterEach(function() { diff --git a/Specs/Scene/PostProcessStageCompositeSpec.js b/Specs/Scene/PostProcessStageCompositeSpec.js index 49043330f3bf..45f73b82b81e 100644 --- a/Specs/Scene/PostProcessStageCompositeSpec.js +++ b/Specs/Scene/PostProcessStageCompositeSpec.js @@ -171,12 +171,12 @@ defineSuite([ var s = createScene(); s.context._depthTexture = false; - if (defined(s._globeDepth)) { - s._globeDepth.destroy(); - s._globeDepth = undefined; - if (defined(s._oit)) { - s._oit.destroy(); - s._oit = undefined; + if (defined(s._view.globeDepth)) { + s._view.globeDepth.destroy(); + s._view.globeDepth = undefined; + if (defined(s._view.oit)) { + s._view.oit.destroy(); + s._view.oit = undefined; } } diff --git a/Specs/Scene/PostProcessStageSpec.js b/Specs/Scene/PostProcessStageSpec.js index b5e6486b79ca..5b815b701c8d 100644 --- a/Specs/Scene/PostProcessStageSpec.js +++ b/Specs/Scene/PostProcessStageSpec.js @@ -196,12 +196,12 @@ defineSuite([ var s = createScene(); s.context._depthTexture = false; - if (defined(s._globeDepth)) { - s._globeDepth.destroy(); - s._globeDepth = undefined; - if (defined(s._oit)) { - s._oit.destroy(); - s._oit = undefined; + if (defined(s._view.globeDepth)) { + s._view.globeDepth.destroy(); + s._view.globeDepth = undefined; + if (defined(s._view.oit)) { + s._view.oit.destroy(); + s._view.oit = undefined; } } diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index d19b70f9e2df..b4a3106c8a47 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -428,12 +428,12 @@ defineSuite([ var camera = scene.camera; var testCamera = new Camera(scene); testCamera.viewBoundingSphere(boxGeometry.boundingSphere); - scene._camera = testCamera; + scene.camera = testCamera; scene.frameState.scene3DOnly = true; verifyPrimitiveRender(primitive); - scene._camera = camera; + scene.camera = camera; }); it('renders with depth fail appearance', function() { diff --git a/Specs/Scene/SceneSpec.js b/Specs/Scene/SceneSpec.js index 6027f800c13b..4d299e9285bc 100644 --- a/Specs/Scene/SceneSpec.js +++ b/Specs/Scene/SceneSpec.js @@ -333,7 +333,7 @@ defineSuite([ }); it('debugShowGlobeDepth', function() { - if(!defined(scene._globeDepth)){ + if (!scene.context.depthTexture) { return; } @@ -702,7 +702,7 @@ defineSuite([ it('copies the globe depth', function() { var scene = createScene(); - if (defined(scene._globeDepth)) { + if (scene.context.depthTexture) { var rectangle = Rectangle.fromDegrees(-100.0, 30.0, -90.0, 40.0); var rectanglePrimitive = createRectangle(rectangle, 1000.0); @@ -1657,7 +1657,7 @@ defineSuite([ function getFrustumCommandsLength(scene) { var commandsLength = 0; - var frustumCommandsList = scene._frustumCommandsList; + var frustumCommandsList = scene.frustumCommandsList; var frustumsLength = frustumCommandsList.length; for (var i = 0; i < frustumsLength; ++i) { var frustumCommands = frustumCommandsList[i]; diff --git a/Specs/Scene/ShadowMapSpec.js b/Specs/Scene/ShadowMapSpec.js index 06ea1505f331..d8609a591018 100644 --- a/Specs/Scene/ShadowMapSpec.js +++ b/Specs/Scene/ShadowMapSpec.js @@ -1071,7 +1071,8 @@ defineSuite([ }); it('model updates derived commands when the shadow map is dirty', function() { - var spy = spyOn(ShadowMap, 'createDerivedCommands').and.callThrough(); + var spy1 = spyOn(ShadowMap, 'createReceiveDerivedCommand').and.callThrough(); + var spy2 = spyOn(ShadowMap, 'createCastDerivedCommand').and.callThrough(); box.show = true; floor.show = true; @@ -1117,18 +1118,10 @@ defineSuite([ scene.render(); } - var callCount; - if (!scene.logarithmicDepthBuffer) { - // Expect derived commands to be updated twice for both the floor and box, - // once on the first frame and again when the shadow map is dirty - callCount = 4; - } else { - // Same as without log z, but doubled. The derived cast commands do not write log z, but - // the derived receive commands do. - callCount = 8; - } - - expect(spy.calls.count()).toEqual(callCount); + // Expect derived commands to be updated twice for both the floor and box, + // once on the first frame and again when the shadow map is dirty + expect(spy1.calls.count()).toEqual(4); + expect(spy2.calls.count()).toEqual(4); box.show = false; floor.show = false; diff --git a/Specs/Scene/SunSpec.js b/Specs/Scene/SunSpec.js index 721444b40bd7..0a3f7d0e148b 100644 --- a/Specs/Scene/SunSpec.js +++ b/Specs/Scene/SunSpec.js @@ -86,7 +86,7 @@ defineSuite([ viewSun(scene.camera, scene.context.uniformState); scene.frameState.passes.render = false; - var command = scene.sun.update(scene.frameState, scene._passState); + var command = scene.sun.update(scene.frameState, scene._view.passState); expect(command).not.toBeDefined(); }); diff --git a/Specs/pick.js b/Specs/pick.js index 129d8db6f34c..22f4e59a88cf 100644 --- a/Specs/pick.js +++ b/Specs/pick.js @@ -6,7 +6,8 @@ define([ 'Renderer/Pass', 'Scene/CreditDisplay', 'Scene/FrameState', - 'Scene/JobScheduler' + 'Scene/JobScheduler', + 'Scene/PickFramebuffer' ], function( BoundingRectangle, Color, @@ -15,7 +16,8 @@ define([ Pass, CreditDisplay, FrameState, - JobScheduler) { + JobScheduler, + PickFramebuffer) { 'use strict'; function executeCommands(context, passState, commands) { @@ -31,7 +33,7 @@ define([ var context = frameState.context; var rectangle = new BoundingRectangle(x, y, 1, 1); - var pickFramebuffer = context.createPickFramebuffer(); + var pickFramebuffer = new PickFramebuffer(context); var passState = pickFramebuffer.begin(rectangle); var oldPasses = frameState.passes;