diff --git a/Apps/Sandcastle/gallery/Classification Types.html b/Apps/Sandcastle/gallery/Classification Types.html index f818b0c10787..c1d6c8d3d4b4 100644 --- a/Apps/Sandcastle/gallery/Classification Types.html +++ b/Apps/Sandcastle/gallery/Classification Types.html @@ -48,7 +48,7 @@ } }); -var options = [{ +var classificationOptions = [{ text : 'Classify Both', onselect : function() { entity.polygon.classificationType = Cesium.ClassificationType.BOTH; @@ -64,7 +64,21 @@ entity.polygon.classificationType = Cesium.ClassificationType.CESIUM_3D_TILE; } }]; -Sandcastle.addToolbarMenu(options); + +var materialOptions = [{ + text : 'Red Material', + onselect : function() { + entity.polygon.material = Cesium.Color.RED.withAlpha(0.5); + } +}, { + text : 'Textured Material', + onselect : function() { + entity.polygon.material = '../images/Cesium_Logo_Color.jpg'; + } +}]; + +Sandcastle.addToolbarMenu(classificationOptions); +Sandcastle.addToolbarMenu(materialOptions); //Sandcastle_End Sandcastle.finishedLoading(); } diff --git a/CHANGES.md b/CHANGES.md index 30522b7c7b57..516df500175b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,11 +1,19 @@ Change Log ========== -### 1.45 - 2019-02-01 +### 1.54 - 2019-02-01 + +##### Breaking Changes :mega: +* Billboards with `HeightReference.CLAMP_TO_GROUND` are now clamped to both terrain and 3D Tiles. +* The default `classificationType` for `GroundPrimitive`, `CorridorGraphics`, `EllipseGraphics`, `PolygonGraphics` and `RectangleGraphics` is now `ClassificationType.BOTH`. + +##### Additions :tada: + +* Added support for textured ground entities (entities with unspecified `height`) and `GroundPrimitives` on 3D Tiles. ##### Fixes :wrench: -* Fixed an issue where classification primitives with the `CESIUM_3D_TILE` classification type would render on terrain. [#6568](https://github.com/AnalyticalGraphicsInc/cesium/issues/6568) -* Fixed an issue where 3D Tiles would show through the globe. [#6867](https://github.com/AnalyticalGraphicsInc/cesium/issues/6867) +* Fixed an issue where classification primitives with the `CESIUM_3D_TILE` classification type would render on terrain. +* Fixed an issue where 3D Tiles would show through the globe. ### 1.53 - 2019-01-02 diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js index b5170a14fa46..f3b8eb4411ca 100644 --- a/Source/DataSources/Entity.js +++ b/Source/DataSources/Entity.js @@ -664,7 +664,7 @@ define([ }; /** - * Checks if the given Scene supports materials besides Color on Entities draped on terrain. + * Checks if the given Scene supports materials besides Color on Entities draped on terrain or 3D Tiles. * If this feature is not supported, Entities with non-color materials but no `height` will * instead be rendered as if height is 0. * diff --git a/Source/DataSources/GeometryUpdater.js b/Source/DataSources/GeometryUpdater.js index 6783a2c650cf..d33253d5d28c 100644 --- a/Source/DataSources/GeometryUpdater.js +++ b/Source/DataSources/GeometryUpdater.js @@ -43,7 +43,7 @@ define([ var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); - var defaultClassificationType = new ConstantProperty(ClassificationType.TERRAIN); + var defaultClassificationType = new ConstantProperty(ClassificationType.BOTH); /** * An abstract class for updating geometry entites. diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index 2f70c1eb260a..7e1ee6c4cf29 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -173,16 +173,10 @@ define([ var groundColorBatches = new Array(numberOfClassificationTypes); var groundMaterialBatches = []; if (supportsMaterialsforEntitiesOnTerrain) { - // Culling, phong shading only supported for ClassificationType.TERRAIN at the moment because - // tileset depth information not yet available. - groundColorBatches[ClassificationType.TERRAIN] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, PerInstanceColorAppearance); for (i = 0; i < numberOfClassificationTypes; ++i) { - if (i !== ClassificationType.TERRAIN) { - groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); - } + groundMaterialBatches.push(new StaticGroundGeometryPerMaterialBatch(groundPrimitives, i, MaterialAppearance)); + groundColorBatches[i] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, i, PerInstanceColorAppearance); } - groundMaterialBatches[0] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, MaterialAppearance); - this._groundTerrainMaterialBatch = groundMaterialBatches[0]; } else { for (i = 0; i < numberOfClassificationTypes; ++i) { groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); @@ -190,10 +184,11 @@ define([ } this._groundColorBatches = groundColorBatches; + this._groundMaterialBatches = groundMaterialBatches; this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives); - this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, groundMaterialBatches, this._dynamicBatch); + this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, this._groundMaterialBatches, this._dynamicBatch); this._subscriptions = new AssociativeArray(); this._updaterSets = new AssociativeArray(); @@ -414,10 +409,7 @@ define([ this._groundColorBatches[classificationType].add(time, updater); } else { // If unsupported, updater will not be on terrain. - // If the updater has a material, ignore input ClassificationType for now and only classify terrain. - // Culling, phong shading only supported for ClassificationType.TERRAIN at the moment because - // tileset depth information not yet available. - this._groundTerrainMaterialBatch.add(time, updater); + this._groundMaterialBatches[classificationType].add(time, updater); } } else if (updater.isClosed) { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { diff --git a/Source/DataSources/GroundGeometryUpdater.js b/Source/DataSources/GroundGeometryUpdater.js index c7fd10b8fe43..97908b9f0228 100644 --- a/Source/DataSources/GroundGeometryUpdater.js +++ b/Source/DataSources/GroundGeometryUpdater.js @@ -1,39 +1,39 @@ define([ - '../Core/ApproximateTerrainHeights', - '../Core/Cartesian3', - '../Core/Check', - '../Core/defaultValue', - '../Core/defined', - '../Core/defineProperties', - '../Core/DeveloperError', - '../Core/GeometryOffsetAttribute', - '../Core/Iso8601', - '../Core/oneTimeWarning', - '../Scene/GroundPrimitive', - '../Scene/HeightReference', - './CallbackProperty', - './ConstantProperty', - './GeometryUpdater', - './Property', - './TerrainOffsetProperty' -], function( - ApproximateTerrainHeights, - Cartesian3, - Check, - defaultValue, - defined, - defineProperties, - DeveloperError, - GeometryOffsetAttribute, - Iso8601, - oneTimeWarning, - GroundPrimitive, - HeightReference, - CallbackProperty, - ConstantProperty, - GeometryUpdater, - Property, - TerrainOffsetProperty) { + '../Core/ApproximateTerrainHeights', + '../Core/Cartesian3', + '../Core/Check', + '../Core/defaultValue', + '../Core/defined', + '../Core/defineProperties', + '../Core/DeveloperError', + '../Core/GeometryOffsetAttribute', + '../Core/Iso8601', + '../Core/oneTimeWarning', + '../Scene/GroundPrimitive', + '../Scene/HeightReference', + './CallbackProperty', + './ConstantProperty', + './GeometryUpdater', + './Property', + './TerrainOffsetProperty' + ], function( + ApproximateTerrainHeights, + Cartesian3, + Check, + defaultValue, + defined, + defineProperties, + DeveloperError, + GeometryOffsetAttribute, + Iso8601, + oneTimeWarning, + GroundPrimitive, + HeightReference, + CallbackProperty, + ConstantProperty, + GeometryUpdater, + Property, + TerrainOffsetProperty) { 'use strict'; var defaultZIndex = new ConstantProperty(0); diff --git a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js index c4fe25feea59..b761892ae5ff 100644 --- a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js +++ b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js @@ -34,8 +34,9 @@ define([ var defaultDistanceDisplayCondition = new DistanceDisplayCondition(); // Encapsulates a Primitive and all the entities that it represents. - function Batch(primitives, appearanceType, materialProperty, usingSphericalTextureCoordinates, zIndex) { + function Batch(primitives, classificationType, appearanceType, materialProperty, usingSphericalTextureCoordinates, zIndex) { this.primitives = primitives; // scene level primitive collection + this.classificationType = classificationType; this.appearanceType = appearanceType; this.materialProperty = materialProperty; this.updaters = new AssociativeArray(); @@ -142,7 +143,7 @@ define([ material : this.material // translucent and closed properties overridden }), - classificationType : ClassificationType.TERRAIN + classificationType : this.classificationType }); primitives.add(primitive, this.zIndex); @@ -266,9 +267,10 @@ define([ /** * @private */ - function StaticGroundGeometryPerMaterialBatch(primitives, appearanceType) { + function StaticGroundGeometryPerMaterialBatch(primitives, classificationType, appearanceType) { this._items = []; this._primitives = primitives; + this._classificationType = classificationType; this._appearanceType = appearanceType; } @@ -293,7 +295,7 @@ define([ } } // If a compatible batch wasn't found, create a new batch. - var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, usingSphericalTextureCoordinates, zIndex); + var batch = new Batch(this._primitives, this._classificationType, this._appearanceType, updater.fillMaterialProperty, usingSphericalTextureCoordinates, zIndex); batch.add(time, updater, geometryInstance); items.push(batch); }; diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index 988f6dbe5c9e..4fc2ed0d50e1 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -167,8 +167,9 @@ define([ }), /** - * An automatic GLSL uniform representing the depth after - * only the globe has been rendered and packed into an RGBA texture. + * An automatic GLSL uniform representing the depth of the scene + * after the globe pass and then updated after the 3D Tiles pass. + * The depth is packed into an RGBA texture. * * @private * diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js index d2c1ca987238..d0dcc4695b7a 100644 --- a/Source/Scene/ClassificationPrimitive.js +++ b/Source/Scene/ClassificationPrimitive.js @@ -67,8 +67,7 @@ define([ * and match most of them and add a new geometry or appearance independently of each other. * Only {@link PerInstanceColorAppearance} with the same color across all instances is supported at this time when using * ClassificationPrimitive directly. - * For full {@link Appearance} support when classifying terrain use {@link GroundPrimitive} instead. - * + * For full {@link Appearance} support when classifying terrain or 3D Tiles use {@link GroundPrimitive} instead. *

*

* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there diff --git a/Source/Scene/GlobeDepth.js b/Source/Scene/GlobeDepth.js index 7076b8ae5f2d..b79f4a644c68 100644 --- a/Source/Scene/GlobeDepth.js +++ b/Source/Scene/GlobeDepth.js @@ -16,7 +16,10 @@ define([ '../Renderer/TextureMinificationFilter', '../Shaders/PostProcessStages/DepthViewPacked', '../Shaders/PostProcessStages/PassThrough', - '../Shaders/PostProcessStages/PassThroughDepth' + '../Shaders/PostProcessStages/PassThroughDepth', + './StencilConstants', + './StencilFunction', + './StencilOperation' ], function( BoundingRectangle, Color, @@ -35,7 +38,10 @@ define([ TextureMinificationFilter, DepthViewPacked, PassThrough, - PassThroughDepth) { + PassThroughDepth, + StencilConstants, + StencilFunction, + StencilOperation) { 'use strict'; /** @@ -45,16 +51,24 @@ define([ this._colorTexture = undefined; this._depthStencilTexture = undefined; this._globeDepthTexture = undefined; + this._tempGlobeDepthTexture = undefined; this.framebuffer = undefined; this._copyDepthFramebuffer = undefined; + this._tempCopyDepthFramebuffer = undefined; + this._updateDepthFramebuffer = undefined; this._clearColorCommand = undefined; this._copyColorCommand = undefined; this._copyDepthCommand = undefined; + this._tempCopyDepthCommand = undefined; + this._updateDepthCommand = undefined; + + this._requiresUpdateDepthResources = false; this._viewport = new BoundingRectangle(); this._rs = undefined; + this._rsUpdate = undefined; this._useScissorTest = false; this._scissorRectangle = undefined; @@ -104,11 +118,41 @@ define([ globeDepth._colorTexture = globeDepth._colorTexture && !globeDepth._colorTexture.isDestroyed() && globeDepth._colorTexture.destroy(); globeDepth._depthStencilTexture = globeDepth._depthStencilTexture && !globeDepth._depthStencilTexture.isDestroyed() && globeDepth._depthStencilTexture.destroy(); globeDepth._globeDepthTexture = globeDepth._globeDepthTexture && !globeDepth._globeDepthTexture.isDestroyed() && globeDepth._globeDepthTexture.destroy(); + globeDepth._tempGlobeDepthTexture = globeDepth._tempGlobeDepthTexture && !globeDepth._tempGlobeDepthTexture.isDestroyed() && globeDepth._tempGlobeDepthTexture.destroy(); } function destroyFramebuffers(globeDepth) { globeDepth.framebuffer = globeDepth.framebuffer && !globeDepth.framebuffer.isDestroyed() && globeDepth.framebuffer.destroy(); globeDepth._copyDepthFramebuffer = globeDepth._copyDepthFramebuffer && !globeDepth._copyDepthFramebuffer.isDestroyed() && globeDepth._copyDepthFramebuffer.destroy(); + globeDepth._tempCopyDepthFramebuffer = globeDepth._tempCopyDepthFramebuffer && !globeDepth._tempCopyDepthFramebuffer.isDestroyed() && globeDepth._tempCopyDepthFramebuffer.destroy(); + globeDepth._updateDepthFramebuffer = globeDepth._updateDepthFramebuffer && !globeDepth._updateDepthFramebuffer.isDestroyed() && globeDepth._updateDepthFramebuffer.destroy(); + } + + function createUpdateDepthResources(globeDepth, context, width, height) { + globeDepth._tempGlobeDepthTexture = new Texture({ + context : context, + width : width, + height : height, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : new Sampler({ + wrapS : TextureWrap.CLAMP_TO_EDGE, + wrapT : TextureWrap.CLAMP_TO_EDGE, + minificationFilter : TextureMinificationFilter.NEAREST, + magnificationFilter : TextureMagnificationFilter.NEAREST + }) + }); + globeDepth._tempCopyDepthFramebuffer = new Framebuffer({ + context : context, + colorTextures : [globeDepth._tempGlobeDepthTexture], + destroyAttachments : false + }); + globeDepth._updateDepthFramebuffer = new Framebuffer({ + context : context, + colorTextures : [globeDepth._globeDepthTexture], + depthStencilTexture : globeDepth._depthStencilTexture, + destroyAttachments : false + }); } function createTextures(globeDepth, context, width, height, hdr) { @@ -173,6 +217,9 @@ define([ destroyFramebuffers(globeDepth); createTextures(globeDepth, context, width, height, hdr); createFramebuffers(globeDepth, context); + if (globeDepth._requiresUpdateDepthResources) { + createUpdateDepthResources(globeDepth, context, width, height); + } } } @@ -197,6 +244,26 @@ define([ rectangle : globeDepth._scissorRectangle } }); + // Copy packed depth only if the 3D Tiles bit is set + globeDepth._rsUpdate = RenderState.fromCache({ + viewport : globeDepth._viewport, + scissorTest : { + enabled : globeDepth._useScissorTest, + rectangle : globeDepth._scissorRectangle + }, + stencilTest : { + enabled : true, + frontFunction : StencilFunction.EQUAL, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }, + backFunction : StencilFunction.NEVER, + reference : StencilConstants.CESIUM_3D_TILE_MASK, + mask : StencilConstants.CESIUM_3D_TILE_MASK + } + }); } if (!defined(globeDepth._copyDepthCommand)) { @@ -211,6 +278,7 @@ define([ } globeDepth._copyDepthCommand.framebuffer = globeDepth._copyDepthFramebuffer; + globeDepth._copyDepthCommand.renderState = globeDepth._rs; if (!defined(globeDepth._copyColorCommand)) { globeDepth._copyColorCommand = context.createViewportQuadCommand(PassThrough, { @@ -223,8 +291,33 @@ define([ }); } - globeDepth._copyDepthCommand.renderState = globeDepth._rs; - globeDepth._copyColorCommand.renderState = globeDepth._rs; + if (!defined(globeDepth._tempCopyDepthCommand)) { + globeDepth._tempCopyDepthCommand = context.createViewportQuadCommand(PassThroughDepth, { + uniformMap : { + u_depthTexture : function() { + return globeDepth._depthStencilTexture; + } + }, + owner : globeDepth + }); + } + + globeDepth._tempCopyDepthCommand.framebuffer = globeDepth._tempCopyDepthFramebuffer; + globeDepth._tempCopyDepthCommand.renderState = globeDepth._rs; + + if (!defined(globeDepth._updateDepthCommand)) { + globeDepth._updateDepthCommand = context.createViewportQuadCommand(PassThrough, { + uniformMap : { + colorTexture : function() { + return globeDepth._tempGlobeDepthTexture; + } + }, + owner : globeDepth + }); + } + + globeDepth._updateDepthCommand.framebuffer = globeDepth._updateDepthFramebuffer; + globeDepth._updateDepthCommand.renderState = globeDepth._rsUpdate; if (!defined(globeDepth._clearColorCommand)) { globeDepth._clearColorCommand = new ClearCommand({ @@ -259,6 +352,32 @@ define([ } }; + GlobeDepth.prototype.executeUpdateDepth = function(context, passState, clearGlobeDepth) { + if (clearGlobeDepth) { + // First copy the depth to a temporary globe depth texture, then update the + // main globe depth texture where the stencil bit for 3D Tiles is set. + // This preserves the original globe depth except where 3D Tiles is rendered. + // The additional texture and framebuffer resources are created on demand. + this._requiresUpdateDepthResources = true; + if (defined(this._updateDepthCommand)) { + if (!defined(this._updateDepthFramebuffer)) { + var width = this._globeDepthTexture.width; + var height = this._globeDepthTexture.height; + createUpdateDepthResources(this, context, width, height); + updateCopyCommands(this, context, width, height, passState); + } + this._tempCopyDepthCommand.execute(context, passState); + this._updateDepthCommand.execute(context, passState); + } + return; + } + + // Fast path - the depth texture can be copied normally. + if (defined(this._copyDepthCommand)) { + this._copyDepthCommand.execute(context, passState); + } + }; + GlobeDepth.prototype.executeCopyColor = function(context, passState) { if (defined(this._copyColorCommand)) { this._copyColorCommand.execute(context, passState); diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 3efbaac2bd55..dbeddae47721 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -67,22 +67,20 @@ define([ }; /** - * A ground primitive represents geometry draped over the terrain in the {@link Scene}. + * A ground primitive represents geometry draped over terrain or 3D Tiles in the {@link Scene}. *

* A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including * {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement, * and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix * and match most of them and add a new geometry or appearance independently of each other. - * - * Only {@link PerInstanceColorAppearance} with the same color across all instances is supported at this time when - * classifying {@link ClassificationType}.CESIUM_3D_TILE and {@link ClassificationType}.BOTH. - * + *

+ *

* Support for the WEBGL_depth_texture extension is required to use GeometryInstances with different PerInstanceColors * or materials besides PerInstanceColorAppearance. - * + *

+ *

* Textured GroundPrimitives were designed for notional patterns and are not meant for precisely mapping * textures to terrain - for that use case, use {@link SingleTileImageryProvider}. - * *

*

* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there @@ -105,7 +103,7 @@ define([ * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory. * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved. * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first. - * @param {ClassificationType} [options.classificationType=ClassificationType.TERRAIN] Determines whether terrain, 3D Tiles or both will be classified. + * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown. * @param {Boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be true on * creation for the volumes to be created before the geometry is released or options.releaseGeometryInstance must be false. @@ -214,9 +212,9 @@ define([ * * @type {ClassificationType} * - * @default ClassificationType.TERRAIN + * @default ClassificationType.BOTH */ - this.classificationType = defaultValue(options.classificationType, ClassificationType.TERRAIN); + this.classificationType = defaultValue(options.classificationType, ClassificationType.BOTH); /** * This property is for debugging only; it is not for production use nor is it optimized. *

@@ -659,12 +657,6 @@ define([ return; } - //>>includeStart('debug', pragmas.debug); - if (this.classificationType !== ClassificationType.TERRAIN && !(this.appearance instanceof PerInstanceColorAppearance)) { - throw new DeveloperError('GroundPrimitives with Materials can only classify ClassificationType.TERRAIN at this time.'); - } - //>>includeEnd('debug'); - var that = this; var primitiveOptions = this._classificationPrimitiveOptions; @@ -712,7 +704,7 @@ define([ this._minHeight = this._minTerrainHeight * exaggeration; this._maxHeight = this._maxTerrainHeight * exaggeration; - var useFragmentCulling = GroundPrimitive._supportsMaterials(frameState.context) && this.classificationType === ClassificationType.TERRAIN; + var useFragmentCulling = GroundPrimitive._supportsMaterials(frameState.context); this._useFragmentCulling = useFragmentCulling; if (useFragmentCulling) { diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 92823beab81b..241ecdbb326c 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -2243,12 +2243,18 @@ define([ executeCommand(commands[j], scene, context, passState); } - // Draw classifications. Modifies 3D Tiles color. - us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION); - commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION]; - length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION]; - for (j = 0; j < length; ++j) { - executeCommand(commands[j], scene, context, passState); + if (length > 0) { + if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { + globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); + } + + // Draw classifications. Modifies 3D Tiles color. + us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION); + commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION]; + length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION]; + for (j = 0; j < length; ++j) { + executeCommand(commands[j], scene, context, passState); + } } } else { // When the invert classification color is opaque: @@ -2318,6 +2324,10 @@ define([ clearClassificationStencil.execute(context, passState); } + if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { + globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); + } + // Draw style over classification. us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION); commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION]; diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index f0fd0c5e426c..489d7694c243 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -911,73 +911,7 @@ defineSuite([ }); }); - it('batches ground entities by identical color if ClassificationType is not TERRAIN', function() { - var entities = new EntityCollection(); - var visualizer = new GeometryVisualizer(scene, entities, scene.primitives, scene.groundPrimitives); - - var blueColor = Color.BLUE.withAlpha(0.5); - entities.add({ - position : new Cartesian3(1, 2, 3), - ellipse : { - semiMajorAxis : 2, - semiMinorAxis : 1, - material : blueColor, - classificationType : ClassificationType.BOTH - } - }); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { - expect(scene.groundPrimitives.length).toEqual(1); - - entities.add({ - position : new Cartesian3(12, 34, 45), - ellipse : { - semiMajorAxis : 2, - semiMinorAxis : 1, - material : blueColor, - classificationType : ClassificationType.BOTH - } - }); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); - }).then(function() { - expect(scene.groundPrimitives.length).toEqual(1); - - entities.add({ - position : new Cartesian3(123, 456, 789), - ellipse : { - semiMajorAxis : 2, - semiMinorAxis : 1, - material : Color.BLUE.withAlpha(0.6), - classificationType : ClassificationType.BOTH - } - }); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); - }).then(function() { - expect(scene.groundPrimitives.length).toEqual(2); - - entities.removeAll(); - visualizer.destroy(); - }); - }); - - it('batches ground entities classifying terrain by material if ground entity materials is supported', function() { + it('batches ground entities by material if ground entity materials is supported', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -1052,13 +986,22 @@ defineSuite([ } }); + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + }).then(function() { + expect(scene.groundPrimitives.length).toEqual(2); + entities.add({ position : Cartesian3.fromDegrees(-12, -34), ellipse : { semiMajorAxis : 2, semiMinorAxis : 1, material : './Data/Images/White.png', - classificationType : ClassificationType.BOTH // expect to render as ClassificationType.TERRAIN + classificationType : ClassificationType.CESIUM_3D_TILE } }); @@ -1069,7 +1012,7 @@ defineSuite([ return isUpdated; }); }).then(function() { - expect(scene.groundPrimitives.length).toEqual(2); + expect(scene.groundPrimitives.length).toEqual(3); entities.removeAll(); visualizer.destroy(); diff --git a/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js b/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js index e90c7393f5b9..4562e01a394e 100644 --- a/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js +++ b/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js @@ -20,6 +20,7 @@ defineSuite([ 'DataSources/PolylineGeometryUpdater', 'DataSources/PolylineGraphics', 'DataSources/TimeIntervalCollectionProperty', + 'Scene/ClassificationType', 'Scene/GroundPrimitive', 'Scene/MaterialAppearance', 'Scene/PolylineColorAppearance', @@ -48,6 +49,7 @@ defineSuite([ PolylineGeometryUpdater, PolylineGraphics, TimeIntervalCollectionProperty, + ClassificationType, GroundPrimitive, MaterialAppearance, PolylineColorAppearance, @@ -80,7 +82,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var ellipse = new EllipseGraphics(); ellipse.semiMajorAxis = new ConstantProperty(2); @@ -151,7 +153,7 @@ defineSuite([ } }); - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var updater = new EllipseGeometryUpdater(entity, scene); batch.add(validTime, updater); @@ -184,7 +186,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); function buildEntity(x, y, z) { var material = new GridMaterialProperty({ @@ -258,7 +260,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var ellipse = new EllipseGraphics(); ellipse.semiMajorAxis = new ConstantProperty(2); @@ -303,7 +305,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var entity = new Entity({ position : new Cartesian3(1234, 5678, 9101112), ellipse : { @@ -349,7 +351,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); function buildEntity(x, y, z) { var material = new GridMaterialProperty({ diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index 65e592793db1..6c8e3d22c64c 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -374,13 +374,15 @@ defineSuite([ expect(frameState.commandList.length).toEqual(0); }); - function expectRender(color) { - expect(scene).toRender(color); + function expectRender(scene, color) { + expect(scene).toRenderAndCall(function(rgba) { + expect(arraySlice(rgba, 0, 4)).toEqual(color); + }); } - function expectRenderBlank() { + function expectRenderBlank(scene) { expect(scene).toRenderAndCall(function(rgba) { - expect(rgba).not.toEqual([0, 0, 0, 255]); + expect(arraySlice(rgba)).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); }); } @@ -391,33 +393,33 @@ defineSuite([ scene.primitives.add(globePrimitive); scene.primitives.add(tilesetPrimitive); - expectRenderBlank(); + expectRenderBlank(scene); scene.groundPrimitives.add(primitive); primitive.classificationType = ClassificationType.BOTH; globePrimitive.show = false; tilesetPrimitive.show = true; - expectRender(color); + expectRender(scene, color); globePrimitive.show = true; tilesetPrimitive.show = false; - expectRender(color); + expectRender(scene, color); primitive.classificationType = ClassificationType.CESIUM_3D_TILE; globePrimitive.show = false; tilesetPrimitive.show = true; - expectRender(color); + expectRender(scene, color); globePrimitive.show = true; tilesetPrimitive.show = false; - expectRenderBlank(); + expectRenderBlank(scene); primitive.classificationType = ClassificationType.TERRAIN; globePrimitive.show = false; tilesetPrimitive.show = true; - expectRenderBlank(); + expectRenderBlank(scene); globePrimitive.show = true; tilesetPrimitive.show = false; - expectRender(color); + expectRender(scene, color); globePrimitive.show = true; tilesetPrimitive.show = true; @@ -565,17 +567,41 @@ defineSuite([ largeScene.camera.setView({destination : destination}); var largeSceneGlobePrimitive = new MockPrimitive(largeSceneReusableGlobePrimitive, Pass.GLOBE); + var largeSceneTilesetPrimitive = new MockPrimitive(largeSceneReusableTilesetPrimitive, Pass.CESIUM_3D_TILE); largeScene.primitives.add(largeSceneGlobePrimitive); - expect(largeScene).toRenderAndCall(function(rgba) { - expect(arraySlice(rgba, 0, 4)).not.toEqual([0, 0, 0, 255]); - expect(rgba[0]).toEqual(0); - }); + largeScene.primitives.add(largeSceneTilesetPrimitive); + + expectRenderBlank(largeScene); largeScene.groundPrimitives.add(groundPrimitive); - expect(largeScene).toRenderAndCall(function(rgba) { - expect(arraySlice(rgba, 0, 4)).toEqual(expectedColor); - }); + + groundPrimitive.classificationType = ClassificationType.BOTH; + largeSceneGlobePrimitive.show = false; + largeSceneTilesetPrimitive.show = true; + expectRender(largeScene, expectedColor); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRender(largeScene, expectedColor); + + groundPrimitive.classificationType = ClassificationType.CESIUM_3D_TILE; + largeSceneGlobePrimitive.show = false; + largeSceneTilesetPrimitive.show = true; + expectRender(largeScene, expectedColor); + globePrimitive.show = true; + largeSceneTilesetPrimitive.show = false; + expectRenderBlank(largeScene); + + groundPrimitive.classificationType = ClassificationType.TERRAIN; + largeSceneGlobePrimitive.show = false; + largeSceneTilesetPrimitive.show = true; + expectRenderBlank(largeScene); + largeSceneGlobePrimitive.show = true; + largeSceneTilesetPrimitive.show = false; + expectRender(largeScene, expectedColor); + + largeSceneGlobePrimitive.show = true; + largeSceneTilesetPrimitive.show = true; } it('renders batched instances', function() { @@ -613,7 +639,7 @@ defineSuite([ verifyLargerScene(batchedPrimitive, [0, 255, 255, 255], rectangle); }); - it('renders small GeometryInstances with texture classifying terrain', function() { + it('renders small GeometryInstances with texture', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -638,14 +664,13 @@ defineSuite([ flat : true, material : whiteImageMaterial }), - asynchronous : false, - classificationType : ClassificationType.TERRAIN + asynchronous : false }); verifyLargerScene(smallRectanglePrimitive, [255, 255, 255, 255], smallRectangle); }); - it('renders large GeometryInstances with texture classifying terrain', function() { + it('renders large GeometryInstances with texture', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -670,14 +695,13 @@ defineSuite([ flat : true, material : whiteImageMaterial }), - asynchronous : false, - classificationType : ClassificationType.TERRAIN + asynchronous : false }); verifyLargerScene(largeRectanglePrimitive, [255, 255, 255, 255], largeRectangle); }); - it('renders GeometryInstances with texture classifying terrain across the IDL', function() { + it('renders GeometryInstances with texture across the IDL', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -699,46 +723,11 @@ defineSuite([ flat : true, material : whiteImageMaterial }), - asynchronous : false, - classificationType : ClassificationType.TERRAIN + asynchronous : false }); verifyLargerScene(largeRectanglePrimitive, [255, 255, 255, 255], largeRectangle); }); - - it('update throws with texture and ClassificationType that is not TERRAIN', function() { - if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { - return; - } - - var whiteImageMaterial = Material.fromType(Material.DiffuseMapType); - whiteImageMaterial.uniforms.image = './Data/Images/White.png'; - - var radians = CesiumMath.toRadians(0.1); - var west = rectangle.west; - var south = rectangle.south; - var smallRectangle = new Rectangle(west, south, west + radians, south + radians); - var smallRectanglePrimitive = new GroundPrimitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : smallRectangle - }), - id : 'smallRectangle' - }), - appearance : new EllipsoidSurfaceAppearance({ - aboveGround : false, - flat : true, - material : whiteImageMaterial - }), - asynchronous : false, - classificationType : ClassificationType.BOTH - }); - - expect(function() { - verifyLargerScene(smallRectanglePrimitive, [255, 255, 255, 255], smallRectangle); - }).toThrowDeveloperError(); - }); }); it('renders with invert classification and an opaque color', function() { @@ -753,8 +742,7 @@ defineSuite([ primitive = new GroundPrimitive({ geometryInstances : rectangleInstance, - asynchronous : false, - classificationType : ClassificationType.BOTH + asynchronous : false }); scene.camera.setView({ destination : rectangle }); @@ -793,8 +781,7 @@ defineSuite([ primitive = new GroundPrimitive({ geometryInstances : rectangleInstance, - asynchronous : false, - classificationType : ClassificationType.BOTH + asynchronous : false }); scene.camera.setView({ destination : rectangle }); @@ -1213,45 +1200,6 @@ defineSuite([ }).toThrowDeveloperError(); }); - it('update throws when batched instance colors are different and ClassificationType is not TERRAIN', function() { - if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { - return; - } - - var rectColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 1.0, 1.0, 1.0)); - var rectangleInstance1 = new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : new Rectangle(rectangle.west, rectangle.south, rectangle.east, (rectangle.north + rectangle.south) * 0.5) - }), - id : 'rectangle1', - attributes : { - color : rectColorAttribute - } - }); - rectColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 1.0, 0.0, 1.0)); - var rectangleInstance2 = new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : new Rectangle(rectangle.west, (rectangle.north + rectangle.south) * 0.5, rectangle.east, rectangle.north) - }), - id : 'rectangle2', - attributes : { - color : rectColorAttribute - } - }); - - primitive = new GroundPrimitive({ - geometryInstances : [rectangleInstance1, rectangleInstance2], - asynchronous : false, - classificationType : ClassificationType.BOTH - }); - - expect(function() { - verifyGroundPrimitiveRender(primitive, rectColorAttribute.value); - }).toThrowDeveloperError(); - }); - it('update throws when one batched instance color is undefined', function() { if (!GroundPrimitive.isSupported(scene)) { return; diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index 692536eab401..8a89b7a66d99 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -218,7 +218,7 @@ defineSuite([ var found = false; var sources = billboardCall.object.shaderProgram.fragmentShaderSource.sources; for (var j = 0; j < sources.length; ++j) { - if (sources[i].indexOf('czm_Debug_main') !== -1) { + if (sources[j].indexOf('czm_Debug_main') !== -1) { found = true; break; }