diff --git a/.gitignore b/.gitignore index 56f10b1afd70..7fedcf343505 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ Thumbs.db /Source/Shaders/*.js /Source/Shaders/*/*.js /Source/Shaders/*/*/*.js +/Source/ThirdParty/Shaders/*.js /Specs/SpecList.js diff --git a/.idea/cesium.iml b/.idea/cesium.iml index 5ecdb1a3e790..9d1caefa1f83 100644 --- a/.idea/cesium.iml +++ b/.idea/cesium.iml @@ -8,5 +8,6 @@ + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml index d45df048bf58..3dd4bfcb6516 100644 --- a/.idea/jsLibraryMappings.xml +++ b/.idea/jsLibraryMappings.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/.idea/runConfigurations/Run_tests.xml b/.idea/runConfigurations/Run_tests.xml index 4a52554ce6db..aeecd6bde9f8 100644 --- a/.idea/runConfigurations/Run_tests.xml +++ b/.idea/runConfigurations/Run_tests.xml @@ -1,9 +1,6 @@ - - - + - diff --git a/Apps/Sandcastle/gallery/Ground Clamping.html b/Apps/Sandcastle/gallery/Ground Clamping.html index f52903ab5a09..66c66bf69620 100644 --- a/Apps/Sandcastle/gallery/Ground Clamping.html +++ b/Apps/Sandcastle/gallery/Ground Clamping.html @@ -149,6 +149,53 @@ viewer.trackedEntity = e; } +}, { + text : 'Sample line positions and draw with depth test disabled', + onselect : function() { + var length = 1000; + + var startLon = Cesium.Math.toRadians(86.953793); + var endLon = Cesium.Math.toRadians(86.896497); + + var lat = Cesium.Math.toRadians(27.988257); + + var terrainSamplePositions = []; + for (var i = 0; i < length; ++i) { + var lon = Cesium.Math.lerp(endLon, startLon, i / (length - 1)); + var position = new Cesium.Cartographic(lon, lat); + terrainSamplePositions.push(position); + } + + Cesium.when(Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, terrainSamplePositions), function(samples) { + var offset = 10.0; + for (var i = 0; i < samples.length; ++i) { + samples[i].height += offset; + } + + viewer.entities.add({ + polyline : { + positions : Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray(samples), + followSurface : false, + width : 5, + material : new Cesium.PolylineOutlineMaterialProperty({ + color : Cesium.Color.ORANGE, + outlineWidth : 2, + outlineColor : Cesium.Color.BLACK + }), + depthFailMaterial : new Cesium.PolylineOutlineMaterialProperty({ + color : Cesium.Color.RED, + outlineWidth : 2, + outlineColor : Cesium.Color.BLACK + }) + } + }); + + var target = new Cesium.Cartesian3(300770.50872389384, 5634912.131394585, 2978152.2865545116); + offset = new Cesium.Cartesian3(6344.974098678562, -793.3419798081741, 2499.9508860763162); + viewer.camera.lookAt(target, offset); + viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + }); + } }], 'zoomButtons'); Sandcastle.reset = function () { diff --git a/CHANGES.md b/CHANGES.md index c690c8543b01..34d583787968 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,9 @@ Change Log ### 1.33 - 2017-05-01 * Added `disableDepthTestDistance` to billboards, points and labels. This sets the distance to the camera where the depth test will be disabled. Setting it to zero (the default) will alwasy enable the depth test. Setting it to `Number.POSITVE_INFINITY` will never enabled the depth test. Also added `scene.minimumDisableDepthTestDistance` to change the default value from zero. [#5166](https://github.com/AnalyticalGraphicsInc/cesium/pull/5166) +* Fixed issue with displaying `MapboxImageryProvider` default token error message [#5191](https://github.com/AnalyticalGraphicsInc/cesium/pull/5191) +* Added a `depthFailMaterial` property to line entities, which is the material used to render the line when it fails the depth test. [#5160](https://github.com/AnalyticalGraphicsInc/cesium/pull/5160) +* Upgrade FXAA to version 3.11. [#5200](https://github.com/AnalyticalGraphicsInc/cesium/pull/5200) * `Scene.pickPosition` now caches results per frame to increase performance [#5117](https://github.com/AnalyticalGraphicsInc/cesium/issues/5117) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1d86d725cef5..7f79121f6061 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -76,6 +76,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu * [Dmitry Kiselev](https://github.com/kiselev-dv) * [Bentley Systems, Inc.](https://www.bentley.com) * [Paul Connelly](https://github.com/pmconne) +* [Flightradar24 AB](https://www.flightradar24.com) + * [Aleksei Kalmykov](https://github.com/kalmykov) ## [Individual CLA](http://www.agi.com/licenses/individual-cla-agi-v1.0.txt) * [Victor Berchet](https://github.com/vicb) diff --git a/LICENSE.md b/LICENSE.md index e95d8ff924ac..13868a3dbfae 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -214,11 +214,11 @@ https://gist.github.com/banksean/300494 > > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -### NVIDIA Image-Based Anti-Aliasing +### NVIDIA GameWorks Graphics Samples -https://developer.nvidia.com/nvidia-graphics-sdk-11-direct3d +https://github.com/NVIDIAGameWorks/GraphicsSamples -> Copyright 2011 NVIDIA Corporation +> Copyright 2016 NVIDIA Corporation > > BY DOWNLOADING THE SOFTWARE AND OTHER AVAILABLE MATERIALS, YOU ("DEVELOPER") AGREE TO BE BOUND BY THE FOLLOWING TERMS AND CONDITIONS > diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index df3cc9e6f5e0..ad62ca0c7be7 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -95,21 +95,31 @@ define([ that._outlineBatches[shadows].add(time, updater); } + var multiplier = 0; + if (defined(updater.depthFailMaterialProperty)) { + multiplier = updater.depthFailMaterialProperty instanceof ColorMaterialProperty ? 1 : 2; + } + + var index; + if (defined(shadows)) { + index = shadows + multiplier * ShadowMode.NUMBER_OF_SHADOW_MODES; + } + if (updater.fillEnabled) { if (updater.onTerrain) { that._groundColorBatch.add(time, updater); } else { if (updater.isClosed) { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { - that._closedColorBatches[shadows].add(time, updater); + that._closedColorBatches[index].add(time, updater); } else { - that._closedMaterialBatches[shadows].add(time, updater); + that._closedMaterialBatches[index].add(time, updater); } } else { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { - that._openColorBatches[shadows].add(time, updater); + that._openColorBatches[index].add(time, updater); } else { - that._openMaterialBatches[shadows].add(time, updater); + that._openMaterialBatches[index].add(time, updater); } } } @@ -152,17 +162,28 @@ define([ var numberOfShadowModes = ShadowMode.NUMBER_OF_SHADOW_MODES; this._outlineBatches = new Array(numberOfShadowModes); - this._closedColorBatches = new Array(numberOfShadowModes); - this._closedMaterialBatches = new Array(numberOfShadowModes); - this._openColorBatches = new Array(numberOfShadowModes); - this._openMaterialBatches = new Array(numberOfShadowModes); + this._closedColorBatches = new Array(numberOfShadowModes * 3); + this._closedMaterialBatches = new Array(numberOfShadowModes * 3); + this._openColorBatches = new Array(numberOfShadowModes * 3); + this._openMaterialBatches = new Array(numberOfShadowModes * 3); for (var i = 0; i < numberOfShadowModes; ++i) { this._outlineBatches[i] = new StaticOutlineGeometryBatch(primitives, scene, i); - this._closedColorBatches[i] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, true, i); - this._closedMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, true, i); - this._openColorBatches[i] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, false, i); - this._openMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, false, i); + + this._closedColorBatches[i] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, undefined, true, i); + this._closedMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, undefined, true, i); + this._openColorBatches[i] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, undefined, false, i); + this._openMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, undefined, false, i); + + this._closedColorBatches[i + numberOfShadowModes] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, type.perInstanceColorAppearanceType, true, i); + this._closedMaterialBatches[i + numberOfShadowModes] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, type.perInstanceColorAppearanceType, true, i); + this._openColorBatches[i + numberOfShadowModes] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, type.perInstanceColorAppearanceType, false, i); + this._openMaterialBatches[i + numberOfShadowModes] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, type.perInstanceColorAppearanceType, false, i); + + this._closedColorBatches[i + numberOfShadowModes * 2] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, type.materialAppearanceType, true, i); + this._closedMaterialBatches[i + numberOfShadowModes * 2] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, type.materialAppearanceType, true, i); + this._openColorBatches[i + numberOfShadowModes * 2] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, type.materialAppearanceType, false, i); + this._openMaterialBatches[i + numberOfShadowModes * 2] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, type.materialAppearanceType, false, i); } this._groundColorBatch = new StaticGroundGeometryColorBatch(groundPrimitives); diff --git a/Source/DataSources/PolylineGeometryUpdater.js b/Source/DataSources/PolylineGeometryUpdater.js index f4714c250878..88ec9894f8b5 100644 --- a/Source/DataSources/PolylineGeometryUpdater.js +++ b/Source/DataSources/PolylineGeometryUpdater.js @@ -99,6 +99,7 @@ define([ this._materialProperty = undefined; this._shadowsProperty = undefined; this._distanceDisplayConditionProperty = undefined; + this._depthFailMaterialProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'polyline', entity.polyline, undefined); } @@ -171,6 +172,18 @@ define([ return this._materialProperty; } }, + /** + * Gets the material property used to fill the geometry when it fails the depth test. + * @memberof PolylineGeometryUpdater.prototype + * + * @type {MaterialProperty} + * @readonly + */ + depthFailMaterialProperty : { + get : function() { + return this._depthFailMaterialProperty; + } + }, /** * Gets a value indicating if the geometry has an outline component. * @memberof PolylineGeometryUpdater.prototype @@ -205,7 +218,7 @@ define([ * Gets the property specifying whether the geometry * casts or receives shadows from each light source. * @memberof PolylineGeometryUpdater.prototype - * + * * @type {Property} * @readonly */ @@ -306,30 +319,32 @@ define([ } //>>includeEnd('debug'); - var color; - var attributes; var entity = this._entity; var isAvailable = entity.isAvailable(time); var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time)); var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); + var attributes = { + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute + }; + + var currentColor; if (this._materialProperty instanceof ColorMaterialProperty) { - var currentColor = Color.WHITE; + currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { currentColor = this._materialProperty.color.getValue(time); } - color = ColorGeometryInstanceAttribute.fromColor(currentColor); - attributes = { - show : show, - distanceDisplayCondition : distanceDisplayConditionAttribute, - color : color - }; - } else { - attributes = { - show : show, - distanceDisplayCondition : distanceDisplayConditionAttribute - }; + attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor); + } + + if (defined(this._depthFailMaterialProperty) && this._depthFailMaterialProperty instanceof ColorMaterialProperty) { + currentColor = Color.WHITE; + if (defined(this._depthFailMaterialProperty.color) && (this._depthFailMaterialProperty.color.isConstant || isAvailable)) { + currentColor = this._depthFailMaterialProperty.color.getValue(time); + } + attributes.depthFailColor = ColorGeometryInstanceAttribute.fromColor(currentColor); } return new GeometryInstance({ @@ -402,6 +417,7 @@ define([ var material = defaultValue(polyline.material, defaultMaterial); var isColorMaterial = material instanceof ColorMaterialProperty; this._materialProperty = material; + this._depthFailMaterialProperty = polyline.depthFailMaterial; this._showProperty = defaultValue(show, defaultShow); this._shadowsProperty = defaultValue(polyline.shadows, defaultShadows); this._distanceDisplayConditionProperty = defaultValue(polyline.distanceDisplayCondition, defaultDistanceDisplayCondition); @@ -431,7 +447,14 @@ define([ return; } - options.vertexFormat = isColorMaterial ? PolylineColorAppearance.VERTEX_FORMAT : PolylineMaterialAppearance.VERTEX_FORMAT; + var vertexFormat; + if (isColorMaterial && (!defined(this._depthFailMaterialProperty) || this._depthFailMaterialProperty instanceof ColorMaterialProperty)) { + vertexFormat = PolylineColorAppearance.VERTEX_FORMAT; + } else { + vertexFormat = PolylineMaterialAppearance.VERTEX_FORMAT; + } + + options.vertexFormat = vertexFormat; options.positions = positions; options.width = defined(width) ? width.getValue(Iso8601.MINIMUM_VALUE) : undefined; options.followSurface = defined(followSurface) ? followSurface.getValue(Iso8601.MINIMUM_VALUE) : undefined; diff --git a/Source/DataSources/PolylineGraphics.js b/Source/DataSources/PolylineGraphics.js index 4b22a4a9602c..d78cad84e1b6 100644 --- a/Source/DataSources/PolylineGraphics.js +++ b/Source/DataSources/PolylineGraphics.js @@ -43,6 +43,8 @@ define([ this._showSubscription = undefined; this._material = undefined; this._materialSubscription = undefined; + this._depthFailMaterial = undefined; + this._depthFailMaterialSubscription = undefined; this._positions = undefined; this._positionsSubscription = undefined; this._followSurface = undefined; @@ -91,6 +93,17 @@ define([ */ material : createMaterialPropertyDescriptor('material'), + /** + * Gets or sets the Property specifying the material used to draw the polyline when it fails the depth test. + *

+ * Requires the EXT_frag_depth WebGL extension to render properly. If the extension is not supported, + * there may be artifacts. + *

+ * @type {MaterialProperty} + * @default undefined + */ + depthFailMaterial : createMaterialPropertyDescriptor('depthFailMaterial'), + /** * Gets or sets the Property specifying the array of {@link Cartesian3} * positions that define the line strip. @@ -123,7 +136,7 @@ define([ * @default Cesium.Math.RADIANS_PER_DEGREE */ granularity : createPropertyDescriptor('granularity'), - + /** * Get or sets the enum Property specifying whether the polyline * casts or receives shadows from each light source. @@ -153,6 +166,7 @@ define([ } result.show = this.show; result.material = this.material; + result.depthFailMaterial = this.depthFailMaterial; result.positions = this.positions; result.width = this.width; result.followSurface = this.followSurface; @@ -177,6 +191,7 @@ define([ this.show = defaultValue(this.show, source.show); this.material = defaultValue(this.material, source.material); + this.depthFailMaterial = defaultValue(this.depthFailMaterial, source.depthFailMaterial); this.positions = defaultValue(this.positions, source.positions); this.width = defaultValue(this.width, source.width); this.followSurface = defaultValue(this.followSurface, source.followSurface); diff --git a/Source/DataSources/StaticGeometryColorBatch.js b/Source/DataSources/StaticGeometryColorBatch.js index eca570d7a0ef..4e6e7aa2fcfc 100644 --- a/Source/DataSources/StaticGeometryColorBatch.js +++ b/Source/DataSources/StaticGeometryColorBatch.js @@ -9,6 +9,8 @@ define([ '../Core/ShowGeometryInstanceAttribute', '../Scene/Primitive', './BoundingSphereState', + './ColorMaterialProperty', + './MaterialProperty', './Property' ], function( AssociativeArray, @@ -20,15 +22,20 @@ define([ ShowGeometryInstanceAttribute, Primitive, BoundingSphereState, + ColorMaterialProperty, + MaterialProperty, Property) { 'use strict'; var colorScratch = new Color(); var distanceDisplayConditionScratch = new DistanceDisplayCondition(); - function Batch(primitives, translucent, appearanceType, closed, shadows) { + function Batch(primitives, translucent, appearanceType, depthFailAppearanceType, depthFailMaterialProperty, closed, shadows) { this.translucent = translucent; this.appearanceType = appearanceType; + this.depthFailAppearanceType = depthFailAppearanceType; + this.depthFailMaterialProperty = depthFailMaterialProperty; + this.depthFailMaterial = undefined; this.closed = closed; this.shadows = shadows; this.primitives = primitives; @@ -43,8 +50,31 @@ define([ this.subscriptions = new AssociativeArray(); this.showsUpdated = new AssociativeArray(); this.itemsToRemove = []; + this.invalidated = false; + + var removeMaterialSubscription; + if (defined(depthFailMaterialProperty)) { + removeMaterialSubscription = depthFailMaterialProperty.definitionChanged.addEventListener(Batch.prototype.onMaterialChanged, this); + } + this.removeMaterialSubscription = removeMaterialSubscription; } + Batch.prototype.onMaterialChanged = function() { + this.invalidated = true; + }; + + Batch.prototype.isMaterial = function(updater) { + var material = this.depthFailMaterialProperty; + var updaterMaterial = updater.depthFailMaterialProperty; + if (updaterMaterial === material) { + return true; + } + if (defined(material)) { + return material.equals(updaterMaterial); + } + return false; + }; + Batch.prototype.add = function(updater, instance) { var id = updater.entity.id; this.createPrimitive = true; @@ -107,9 +137,24 @@ define([ if (defined(originalAttributes.color)) { originalAttributes.color.value = attributes.color; } + if (defined(originalAttributes.depthFailColor)) { + originalAttributes.depthFailColor.value = attributes.depthFailColor; + } } } + var depthFailAppearance; + if (defined(this.depthFailAppearanceType)) { + if (defined(this.depthFailMaterialProperty)) { + this.depthFailMaterial = MaterialProperty.getValue(time, this.depthFailMaterialProperty, this.depthFailMaterial); + } + depthFailAppearance = new this.depthFailAppearanceType({ + material : this.depthFailMaterial, + translucent : this.translucent, + closed : this.closed + }); + } + primitive = new Primitive({ asynchronous : true, geometryInstances : geometries, @@ -117,6 +162,7 @@ define([ translucent : this.translucent, closed : this.closed }), + depthFailAppearance : depthFailAppearance, shadows : this.shadows }); primitives.add(primitive); @@ -142,6 +188,12 @@ define([ primitives.remove(this.oldPrimitive); this.oldPrimitive = undefined; } + + if (defined(this.depthFailAppearanceType) && !(this.depthFailMaterialProperty instanceof ColorMaterialProperty)) { + this.depthFailMaterial = MaterialProperty.getValue(time, this.depthFailMaterialProperty, this.depthFailMaterial); + this.primitive.depthFailAppearance.material = this.depthFailMaterial; + } + var updatersWithAttributes = this.updatersWithAttributes.values; var length = updatersWithAttributes.length; var waitingOnCreate = this.waitingOnCreate; @@ -167,6 +219,15 @@ define([ } } + if (defined(this.depthFailAppearanceType) && this.depthFailAppearanceType instanceof ColorMaterialProperty && (!updater.depthFailMaterialProperty.isConstant || waitingOnCreate)) { + var depthFailColorProperty = updater.depthFailMaterialProperty.color; + depthFailColorProperty.getValue(time, colorScratch); + if (!Color.equals(attributes._lastDepthFailColor, colorScratch)) { + attributes._lastDepthFailColor = Color.clone(colorScratch, attributes._lastDepthFailColor); + attributes.depthFailColor = ColorGeometryInstanceAttribute.toValue(colorScratch, attributes.depthFailColor); + } + } + var show = updater.entity.isShowing && (updater.hasConstantFill || updater.isFilled(time)); var currentShow = attributes.show[0] === 1; if (show !== currentShow) { @@ -250,80 +311,170 @@ define([ } }; + Batch.prototype.destroy = function() { + var primitive = this.primitive; + var primitives = this.primitives; + if (defined(primitive)) { + primitives.remove(primitive); + } + var oldPrimitive = this.oldPrimitive; + if (defined(oldPrimitive)) { + primitives.remove(oldPrimitive); + } + if(defined(this.removeMaterialSubscription)) { + this.removeMaterialSubscription(); + } + }; + /** * @private */ - function StaticGeometryColorBatch(primitives, appearanceType, closed, shadows) { - this._solidBatch = new Batch(primitives, false, appearanceType, closed, shadows); - this._translucentBatch = new Batch(primitives, true, appearanceType, closed, shadows); + function StaticGeometryColorBatch(primitives, appearanceType, depthFailAppearanceType, closed, shadows) { + this._solidItems = []; + this._translucentItems = []; + this._primitives = primitives; + this._appearanceType = appearanceType; + this._depthFailAppearanceType = depthFailAppearanceType; + this._closed = closed; + this._shadows = shadows; } StaticGeometryColorBatch.prototype.add = function(time, updater) { + var items; + var translucent; var instance = updater.createFillGeometryInstance(time); if (instance.attributes.color.value[3] === 255) { - this._solidBatch.add(updater, instance); + items = this._solidItems; + translucent = false; } else { - this._translucentBatch.add(updater, instance); + items = this._translucentItems; + translucent = true; } - }; - StaticGeometryColorBatch.prototype.remove = function(updater) { - if (!this._solidBatch.remove(updater)) { - this._translucentBatch.remove(updater); + var length = items.length; + for (var i = 0; i < length; i++) { + var item = items[i]; + if (item.isMaterial(updater)) { + item.add(updater, instance); + return; + } } + var batch = new Batch(this._primitives, translucent, this._appearanceType, this._depthFailAppearanceType, updater.depthFailMaterialProperty, this._closed, this._shadows); + batch.add(updater, instance); + items.push(batch); }; - StaticGeometryColorBatch.prototype.update = function(time) { - var i; - var updater; + function removeItem(items, updater) { + var length = items.length; + for (var i = length - 1; i >= 0; i--) { + var item = items[i]; + if (item.remove(updater)) { + if (item.updaters.length === 0) { + items.splice(i, 1); + item.destroy(); + return true; + } + } + } + return false; + } - //Perform initial update - var isUpdated = this._solidBatch.update(time); - isUpdated = this._translucentBatch.update(time) && isUpdated; + StaticGeometryColorBatch.prototype.remove = function(updater) { + if (!removeItem(this._solidItems, updater)) { + removeItem(this._translucentItems, updater); + } + }; - //If any items swapped between solid/translucent, we need to - //move them between batches - var itemsToRemove = this._solidBatch.itemsToRemove; - var solidsToMoveLength = itemsToRemove.length; - if (solidsToMoveLength > 0) { - for (i = 0; i < solidsToMoveLength; i++) { - updater = itemsToRemove[i]; - this._solidBatch.remove(updater); - this._translucentBatch.add(updater, updater.createFillGeometryInstance(time)); + function moveItems(batch, items, time) { + var itemsMoved = false; + var length = items.length; + for (var i = 0; i < length; ++i) { + var item = items[i]; + var itemsToRemove = item.itemsToRemove; + var itemsToMoveLength = itemsToRemove.length; + if (itemsToMoveLength > 0) { + for (i = 0; i < itemsToMoveLength; i++) { + var updater = itemsToRemove[i]; + item.remove(updater); + batch.add(time, updater); + itemsMoved = true; + } } } + return itemsMoved; + } - itemsToRemove = this._translucentBatch.itemsToRemove; - var translucentToMoveLength = itemsToRemove.length; - if (translucentToMoveLength > 0) { - for (i = 0; i < translucentToMoveLength; i++) { - updater = itemsToRemove[i]; - this._translucentBatch.remove(updater); - this._solidBatch.add(updater, updater.createFillGeometryInstance(time)); + function updateItems(batch, items, time, isUpdated) { + var length = items.length; + for (i = length - 1; i >= 0; i--) { + var item = items[i]; + if (item.invalidated) { + items.splice(i, 1); + var updaters = item.updaters.values; + var updatersLength = updaters.length; + for (var h = 0; h < updatersLength; h++) { + batch.add(time, updaters[h]); + } + item.destroy(); } } + length = items.length; + for (var i = 0; i < length; ++i) { + isUpdated = items[i].update(time) && isUpdated; + } + return isUpdated; + } + + StaticGeometryColorBatch.prototype.update = function(time) { + //Perform initial update + var isUpdated = updateItems(this, this._solidItems, time, true); + isUpdated = updateItems(this, this._translucentItems, time, isUpdated) && isUpdated; + + //If any items swapped between solid/translucent, we need to + //move them between batches + var solidsMoved = moveItems(this, this._solidItems, time); + var translucentsMoved = moveItems(this, this._translucentItems, time); + //If we moved anything around, we need to re-build the primitive - if (solidsToMoveLength > 0 || translucentToMoveLength > 0) { - isUpdated = this._solidBatch.update(time) && isUpdated; - isUpdated = this._translucentBatch.update(time) && isUpdated; + if (solidsMoved || translucentsMoved) { + isUpdated = updateItems(this, this._solidItems, time, isUpdated) && isUpdated; + isUpdated = updateItems(this, this._translucentItems, time, isUpdated)&& isUpdated; } return isUpdated; }; - StaticGeometryColorBatch.prototype.getBoundingSphere = function(entity, result) { - if (this._solidBatch.contains(entity)) { - return this._solidBatch.getBoundingSphere(entity, result); - } else if (this._translucentBatch.contains(entity)) { - return this._translucentBatch.getBoundingSphere(entity, result); + function getBoundingSphere(items, entity, result) { + var length = items.length; + for (var i = 0; i < length; i++) { + var item = items[i]; + if(item.contains(entity)){ + return item.getBoundingSphere(entity, result); + } } return BoundingSphereState.FAILED; + } + + StaticGeometryColorBatch.prototype.getBoundingSphere = function(entity, result) { + var boundingSphere = getBoundingSphere(this._solidItems, entity, result); + if (boundingSphere === BoundingSphereState.FAILED) { + return getBoundingSphere(this._translucentItems, entity, result); + } + return boundingSphere; }; + function removeAllPrimitives(items) { + var length = items.length; + for (var i = 0; i < length; i++) { + items[i].destroy(); + } + items.length = 0; + } + StaticGeometryColorBatch.prototype.removeAllPrimitives = function() { - this._solidBatch.removeAllPrimitives(); - this._translucentBatch.removeAllPrimitives(); + removeAllPrimitives(this._solidItems); + removeAllPrimitives(this._translucentItems); }; return StaticGeometryColorBatch; diff --git a/Source/DataSources/StaticGeometryPerMaterialBatch.js b/Source/DataSources/StaticGeometryPerMaterialBatch.js index df16c8ebf9cc..527c6690130c 100644 --- a/Source/DataSources/StaticGeometryPerMaterialBatch.js +++ b/Source/DataSources/StaticGeometryPerMaterialBatch.js @@ -1,32 +1,40 @@ /*global define*/ define([ '../Core/AssociativeArray', + '../Core/Color', + '../Core/ColorGeometryInstanceAttribute', '../Core/defined', '../Core/DistanceDisplayCondition', '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/ShowGeometryInstanceAttribute', '../Scene/Primitive', './BoundingSphereState', + './ColorMaterialProperty', './MaterialProperty', './Property' ], function( AssociativeArray, + Color, + ColorGeometryInstanceAttribute, defined, DistanceDisplayCondition, DistanceDisplayConditionGeometryInstanceAttribute, ShowGeometryInstanceAttribute, Primitive, BoundingSphereState, + ColorMaterialProperty, MaterialProperty, Property) { 'use strict'; var distanceDisplayConditionScratch = new DistanceDisplayCondition(); - function Batch(primitives, appearanceType, materialProperty, closed, shadows) { + function Batch(primitives, appearanceType, materialProperty, depthFailAppearanceType, depthFailMaterialProperty, closed, shadows) { this.primitives = primitives; this.appearanceType = appearanceType; this.materialProperty = materialProperty; + this.depthFailAppearanceType = depthFailAppearanceType; + this.depthFailMaterialProperty = depthFailMaterialProperty; this.closed = closed; this.shadows = shadows; this.updaters = new AssociativeArray(); @@ -35,6 +43,7 @@ define([ this.oldPrimitive = undefined; this.geometry = new AssociativeArray(); this.material = undefined; + this.depthFailMaterial = undefined; this.updatersWithAttributes = new AssociativeArray(); this.attributes = new AssociativeArray(); this.invalidated = false; @@ -42,6 +51,7 @@ define([ this.subscriptions = new AssociativeArray(); this.showsUpdated = new AssociativeArray(); } + Batch.prototype.onMaterialChanged = function() { this.invalidated = true; }; @@ -49,13 +59,15 @@ define([ Batch.prototype.isMaterial = function(updater) { var material = this.materialProperty; var updaterMaterial = updater.fillMaterialProperty; - if (updaterMaterial === material) { + var depthFailMaterial = this.depthFailMaterialProperty; + var updaterDepthFailMaterial = updater.depthFailMaterialProperty; + + if (updaterMaterial === material && updaterDepthFailMaterial === depthFailMaterial) { return true; } - if (defined(material)) { - return material.equals(updaterMaterial); - } - return false; + var equals = defined(material) && material.equals(updaterMaterial); + equals = ((!defined(depthFailMaterial) && !defined(updaterDepthFailMaterial)) || (defined(depthFailMaterial) && depthFailMaterial.equals(updaterDepthFailMaterial))) && equals; + return equals; }; Batch.prototype.add = function(time, updater) { @@ -89,6 +101,8 @@ define([ return this.createPrimitive; }; + var colorScratch = new Color(); + Batch.prototype.update = function(time) { var isUpdated = true; var primitive = this.primitive; @@ -120,10 +134,30 @@ define([ if (defined(originalAttributes.color)) { originalAttributes.color.value = attributes.color; } + if (defined(originalAttributes.depthFailColor)) { + originalAttributes.depthFailColor.value = attributes.depthFailColor; + } } } this.material = MaterialProperty.getValue(time, this.materialProperty, this.material); + + var depthFailAppearance; + if (defined(this.depthFailMaterialProperty)) { + var translucent; + if (this.depthFailMaterialProperty instanceof MaterialProperty) { + this.depthFailMaterial = MaterialProperty.getValue(time, this.depthFailMaterialProperty, this.depthFailMaterial); + translucent = this.depthFailMaterial.isTranslucent(); + } else { + translucent = this.material.isTranslucent(); + } + depthFailAppearance = new this.depthFailAppearanceType({ + material : this.depthFailMaterial, + translucent : translucent, + closed : this.closed + }); + } + primitive = new Primitive({ asynchronous : true, geometryInstances : geometries, @@ -132,6 +166,7 @@ define([ translucent : this.material.isTranslucent(), closed : this.closed }), + depthFailAppearance : depthFailAppearance, shadows : this.shadows }); @@ -161,6 +196,11 @@ define([ this.material = MaterialProperty.getValue(time, this.materialProperty, this.material); this.primitive.appearance.material = this.material; + if (defined(this.depthFailAppearanceType) && !(this.depthFailMaterialProperty instanceof ColorMaterialProperty)) { + this.depthFailMaterial = MaterialProperty.getValue(time, this.depthFailMaterialProperty, this.depthFailMaterial); + this.primitive.depthFailAppearance.material = this.depthFailMaterial; + } + var updatersWithAttributes = this.updatersWithAttributes.values; var length = updatersWithAttributes.length; for (i = 0; i < length; i++) { @@ -174,6 +214,15 @@ define([ this.attributes.set(instance.id.id, attributes); } + if (defined(this.depthFailAppearanceType) && this.depthFailAppearanceType instanceof ColorMaterialProperty && !updater.depthFailMaterialProperty.isConstant) { + var depthFailColorProperty = updater.depthFailMaterialProperty.color; + depthFailColorProperty.getValue(time, colorScratch); + if (!Color.equals(attributes._lastDepthFailColor, colorScratch)) { + attributes._lastDepthFailColor = Color.clone(colorScratch, attributes._lastDepthFailColor); + attributes.depthFailColor = ColorGeometryInstanceAttribute.toValue(colorScratch, attributes.depthFailColor); + } + } + var show = entity.isShowing && (updater.hasConstantFill || updater.isFilled(time)); var currentShow = attributes.show[0] === 1; if (show !== currentShow) { @@ -238,7 +287,7 @@ define([ return BoundingSphereState.DONE; }; - Batch.prototype.destroy = function(time) { + Batch.prototype.destroy = function() { var primitive = this.primitive; var primitives = this.primitives; if (defined(primitive)) { @@ -254,13 +303,15 @@ define([ /** * @private */ - function StaticGeometryPerMaterialBatch(primitives, appearanceType, closed, shadows) { + function StaticGeometryPerMaterialBatch(primitives, appearanceType, depthFailAppearanceType, closed, shadows) { this._items = []; this._primitives = primitives; this._appearanceType = appearanceType; + this._depthFailAppearanceType = depthFailAppearanceType; this._closed = closed; this._shadows = shadows; } + StaticGeometryPerMaterialBatch.prototype.add = function(time, updater) { var items = this._items; var length = items.length; @@ -271,7 +322,7 @@ define([ return; } } - var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, this._closed, this._shadows); + var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, this._depthFailAppearanceType, updater.depthFailMaterialProperty, this._closed, this._shadows); batch.add(time, updater); items.push(batch); }; diff --git a/Source/Scene/FXAA.js b/Source/Scene/FXAA.js index 783bb7485c49..46f1342678a1 100644 --- a/Source/Scene/FXAA.js +++ b/Source/Scene/FXAA.js @@ -12,8 +12,13 @@ define([ '../Renderer/Renderbuffer', '../Renderer/RenderbufferFormat', '../Renderer/RenderState', + '../Renderer/Sampler', '../Renderer/Texture', - '../Shaders/PostProcessFilters/FXAA' + '../Renderer/TextureMagnificationFilter', + '../Renderer/TextureMinificationFilter', + '../Renderer/TextureWrap', + '../Shaders/PostProcessFilters/FXAA', + '../ThirdParty/Shaders/FXAA3_11' ], function( BoundingRectangle, Cartesian2, @@ -27,14 +32,19 @@ define([ Renderbuffer, RenderbufferFormat, RenderState, + Sampler, Texture, - FXAAFS) { + TextureMagnificationFilter, + TextureMinificationFilter, + TextureWrap, + FXAAFS, + FXAA3_11) { 'use strict'; /** * @private */ - function FXAA(context) { + function FXAA() { this._texture = undefined; this._depthStencilTexture = undefined; this._depthStencilRenderbuffer = undefined; @@ -50,6 +60,8 @@ define([ owner : this }); this._clearCommand = clearCommand; + + this._qualityPreset = 39; } function destroyResources(fxaa) { @@ -85,7 +97,13 @@ define([ width : width, height : height, pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.UNSIGNED_BYTE + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : new Sampler({ + wrapS : TextureWrap.CLAMP_TO_EDGE, + wrapT : TextureWrap.CLAMP_TO_EDGE, + minificationFilter : TextureMinificationFilter.LINEAR, + magnificationFilter : TextureMagnificationFilter.LINEAR + }) }); if (context.depthTexture) { @@ -119,7 +137,12 @@ define([ } if (!defined(this._command)) { - this._command = context.createViewportQuadCommand(FXAAFS, { + var fs = + '#define FXAA_QUALITY_PRESET ' + this._qualityPreset + '\n' + + FXAA3_11 + '\n' + + FXAAFS; + + this._command = context.createViewportQuadCommand(fs, { owner : this }); } @@ -137,13 +160,13 @@ define([ if (textureChanged) { var that = this; - var step = new Cartesian2(1.0 / this._texture.width, 1.0 / this._texture.height); + var rcpFrame = new Cartesian2(1.0 / this._texture.width, 1.0 / this._texture.height); this._command.uniformMap = { u_texture : function() { return that._texture; }, - u_step : function() { - return step; + u_fxaaQualityRcpFrame : function() { + return rcpFrame; } }; } diff --git a/Source/Scene/MapboxImageryProvider.js b/Source/Scene/MapboxImageryProvider.js index fd17812a3d9d..4e725a2023f9 100644 --- a/Source/Scene/MapboxImageryProvider.js +++ b/Source/Scene/MapboxImageryProvider.js @@ -65,7 +65,7 @@ define([ this._url = url; this._mapId = mapId; this._accessToken = MapboxApi.getAccessToken(options.accessToken); - this._accessTokenErrorCredit = MapboxApi.getErrorCredit(options.key); + this._accessTokenErrorCredit = MapboxApi.getErrorCredit(options.accessToken); var format = defaultValue(options.format, 'png'); if (!/\./.test(format)) { format = '.' + format; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 8dac7a799c42..9b1afab234ce 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -35,6 +35,9 @@ define([ '../ThirdParty/when', './BatchTable', './CullFace', + './DepthFunction', + './Material', + './PolylineMaterialAppearance', './PrimitivePipeline', './PrimitiveState', './SceneMode', @@ -75,6 +78,9 @@ define([ when, BatchTable, CullFace, + DepthFunction, + Material, + PolylineMaterialAppearance, PrimitivePipeline, PrimitiveState, SceneMode, @@ -207,7 +213,7 @@ define([ this.geometryInstances = options.geometryInstances; /** - * The {@link Appearance} used to shade this primitive. Each geometry + * The {@link Appearance} used to shade this primitive. Each geometry * instance is shaded with the same appearance. Some appearances, like * {@link PerInstanceColorAppearance} allow giving each instance unique * properties. @@ -220,6 +226,29 @@ define([ this._appearance = undefined; this._material = undefined; + /** + * The {@link Appearance} used to shade this primitive when it fails the depth test. Each geometry + * instance is shaded with the same appearance. Some appearances, like + * {@link PerInstanceColorAppearance} allow giving each instance unique + * properties. + * + *

+ * When using an appearance that requires a color attribute, like PerInstanceColorAppearance, + * add a depthFailColor per-instance attribute instead. + *

+ * + *

+ * Requires the EXT_frag_depth WebGL extension to render properly. If the extension is not supported, + * there may be artifacts. + *

+ * @type Appearance + * + * @default undefined + */ + this.depthFailAppearance = options.depthFailAppearance; + this._depthFailAppearance = undefined; + this._depthFailMaterial = undefined; + /** * The 4x4 transformation matrix that transforms the primitive (all geometry instances) from model to world coordinates. * When this is the identity matrix, the primitive is drawn in world coordinates, i.e., Earth's WGS84 coordinates. @@ -325,6 +354,11 @@ define([ this._backFaceRS = undefined; this._sp = undefined; + this._depthFailAppearance = undefined; + this._spDepthFail = undefined; + this._frontFaceDepthFailRS = undefined; + this._backFaceDepthFailRS = undefined; + this._pickRS = undefined; this._pickSP = undefined; this._pickIds = []; @@ -794,10 +828,10 @@ define([ return renamedVS + '\n' + showMain; }; - Primitive._updateColorAttribute = function(primitive, vertexShaderSource) { + Primitive._updateColorAttribute = function(primitive, vertexShaderSource, isDepthFail) { // some appearances have a color attribute for per vertex color. // only remove if color is a per instance attribute. - if (!defined(primitive._batchTableAttributeIndices.color)) { + if (!defined(primitive._batchTableAttributeIndices.color) && !defined(primitive._batchTableAttributeIndices.depthFailColor)) { return vertexShaderSource; } @@ -805,9 +839,19 @@ define([ return vertexShaderSource; } + //>>includeStart('debug', pragmas.debug); + if (isDepthFail && !defined(primitive._batchTableAttributeIndices.depthFailColor)) { + throw new DeveloperError('A depthFailColor per-instance attribute is required when using a depth fail appearance that uses a color attribute.'); + } + //>>includeEnd('debug'); + var modifiedVS = vertexShaderSource; modifiedVS = modifiedVS.replace(/attribute\s+vec4\s+color;/g, ''); - modifiedVS = modifiedVS.replace(/(\b)color(\b)/g, '$1czm_batchTable_color(batchId)$2'); + if (!isDepthFail) { + modifiedVS = modifiedVS.replace(/(\b)color(\b)/g, '$1czm_batchTable_color(batchId)$2'); + } else { + modifiedVS = modifiedVS.replace(/(\b)color(\b)/g, '$1czm_batchTable_depthFailColor(batchId)$2'); + } return modifiedVS; }; @@ -947,6 +991,44 @@ define([ return [attributeDecl, globalDecl, modifiedVS, compressedMain].join('\n'); } + function depthClampVS(vertexShaderSource) { + var modifiedVS = ShaderSource.replaceMain(vertexShaderSource, 'czm_non_depth_clamp_main'); + modifiedVS += + '#ifdef GL_EXT_frag_depth\n' + + 'varying float v_WindowZ;\n' + + '#endif\n' + + 'void main() {\n' + + ' czm_non_depth_clamp_main();\n' + + ' vec4 position = gl_Position;\n' + + '#ifdef GL_EXT_frag_depth\n' + + ' v_WindowZ = (0.5 * (position.z / position.w) + 0.5) * position.w;\n' + + '#endif\n' + + ' position.z = min(position.z, position.w);\n' + + ' gl_Position = position;' + + '}\n'; + return modifiedVS; + } + + function depthClampFS(fragmentShaderSource) { + var modifiedFS = ShaderSource.replaceMain(fragmentShaderSource, 'czm_non_depth_clamp_main'); + modifiedFS += + '#ifdef GL_EXT_frag_depth\n' + + 'varying float v_WindowZ;\n' + + '#endif\n' + + 'void main() {\n' + + ' czm_non_depth_clamp_main();\n' + + '#ifdef GL_EXT_frag_depth\n' + + ' gl_FragDepthEXT = min(v_WindowZ * gl_FragCoord.w, 1.0);\n' + + '#endif\n' + + '}\n'; + modifiedFS = + '#ifdef GL_EXT_frag_depth\n' + + '#extension GL_EXT_frag_depth : enable\n' + + '#endif\n' + + modifiedFS; + return modifiedFS; + } + function validateShaderMatching(shaderProgram, attributeLocations) { // For a VAO and shader program to be compatible, the VAO must have // all active attribute in the shader program. The VAO may have @@ -1315,6 +1397,25 @@ define([ primitive._pickRS = RenderState.fromCache(rs); } } + + if (defined(primitive._depthFailAppearance)) { + renderState = primitive._depthFailAppearance.getRenderState(); + rs = clone(renderState, false); + rs.depthTest.func = DepthFunction.GREATER; + if (twoPasses) { + rs.cull = { + enabled : true, + face : CullFace.BACK + }; + primitive._frontFaceDepthFailRS = RenderState.fromCache(rs); + + rs.cull.face = CullFace.FRONT; + primitive._backFaceDepthFailRS = RenderState.fromCache(rs); + } else { + primitive._frontFaceDepthFailRS = RenderState.fromCache(rs); + primitive._backFaceDepthFailRS = primitive._frontFaceRS; + } + } } function createShaderProgram(primitive, frameState, appearance) { @@ -1325,7 +1426,7 @@ define([ var vs = primitive._batchTable.getVertexShaderCallback()(appearance.vertexShaderSource); vs = Primitive._appendShowToShader(primitive, vs); vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs, frameState.scene3DOnly); - vs = Primitive._updateColorAttribute(primitive, vs); + vs = Primitive._updateColorAttribute(primitive, vs, false); vs = modifyForEncodedNormals(primitive, vs); vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); var fs = appearance.getFragmentShaderSource(); @@ -1360,12 +1461,30 @@ define([ attributeLocations : attributeLocations }); validateShaderMatching(primitive._sp, attributeLocations); - } - var modifiedModelViewScratch = new Matrix4(); - var rtcScratch = new Cartesian3(); + if (defined(primitive._depthFailAppearance)) { + vs = primitive._batchTable.getVertexShaderCallback()(primitive._depthFailAppearance.vertexShaderSource); + vs = Primitive._appendShowToShader(primitive, vs); + vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs, frameState.scene3DOnly); + vs = Primitive._updateColorAttribute(primitive, vs, true); + vs = modifyForEncodedNormals(primitive, vs); + vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); + vs = depthClampVS(vs); - function createCommands(primitive, appearance, material, translucent, twoPasses, colorCommands, pickCommands, frameState) { + fs = depthClampFS(primitive._depthFailAppearance.getFragmentShaderSource()); + + primitive._spDepthFail = ShaderProgram.replaceCache({ + context : context, + shaderProgram : primitive._spDepthFail, + vertexShaderSource : vs, + fragmentShaderSource : fs, + attributeLocations : attributeLocations + }); + validateShaderMatching(primitive._spDepthFail, attributeLocations); + } + } + + function getUniforms(primitive, appearance, material, frameState) { // Create uniform map by combining uniforms from the appearance and material if either have uniforms. var materialUniformMap = defined(material) ? material._uniforms : undefined; var appearanceUniformMap = {}; @@ -1398,9 +1517,26 @@ define([ }; } + return uniforms; + } + + var modifiedModelViewScratch = new Matrix4(); + var rtcScratch = new Cartesian3(); + + function createCommands(primitive, appearance, material, translucent, twoPasses, colorCommands, pickCommands, frameState) { + var uniforms = getUniforms(primitive, appearance, material, frameState); + + var depthFailUniforms; + if (defined(primitive._depthFailAppearance)) { + depthFailUniforms = getUniforms(primitive, primitive._depthFailAppearance, primitive._depthFailAppearance.material, frameState); + } + var pass = translucent ? Pass.TRANSLUCENT : Pass.OPAQUE; - colorCommands.length = primitive._va.length * (twoPasses ? 2 : 1); + var multiplier = twoPasses ? 2 : 1; + multiplier *= defined(primitive._depthFailAppearance) ? 2 : 1; + + colorCommands.length = primitive._va.length * multiplier; pickCommands.length = primitive._va.length; var length = colorCommands.length; @@ -1409,6 +1545,40 @@ define([ for (var i = 0; i < length; ++i) { var colorCommand; + if (defined(primitive._depthFailAppearance)) { + if (twoPasses) { + colorCommand = colorCommands[i]; + if (!defined(colorCommand)) { + colorCommand = colorCommands[i] = new DrawCommand({ + owner : primitive, + primitiveType : primitive._primitiveType + }); + } + colorCommand.vertexArray = primitive._va[vaIndex]; + colorCommand.renderState = primitive._backFaceDepthFailRS; + colorCommand.shaderProgram = primitive._spDepthFail; + colorCommand.uniformMap = depthFailUniforms; + colorCommand.pass = pass; + + ++i; + } + + colorCommand = colorCommands[i]; + if (!defined(colorCommand)) { + colorCommand = colorCommands[i] = new DrawCommand({ + owner : primitive, + primitiveType : primitive._primitiveType + }); + } + colorCommand.vertexArray = primitive._va[vaIndex]; + colorCommand.renderState = primitive._frontFaceDepthFailRS; + colorCommand.shaderProgram = primitive._spDepthFail; + colorCommand.uniformMap = depthFailUniforms; + colorCommand.pass = pass; + + ++i; + } + if (twoPasses) { colorCommand = colorCommands[i]; if (!defined(colorCommand)) { @@ -1515,8 +1685,12 @@ define([ var castShadows = ShadowMode.castShadows(primitive.shadows); var receiveShadows = ShadowMode.receiveShadows(primitive.shadows); var colorLength = colorCommands.length; + + var factor = twoPasses ? 2 : 1; + factor *= defined(primitive._depthFailAppearance) ? 2 : 1; + for (var j = 0; j < colorLength; ++j) { - var sphereIndex = twoPasses ? Math.floor(j / 2) : j; + var sphereIndex = Math.floor(j / factor); var colorCommand = colorCommands[j]; colorCommand.modelMatrix = modelMatrix; colorCommand.boundingVolume = boundingSpheres[sphereIndex]; @@ -1622,6 +1796,19 @@ define([ createSP = true; } + var depthFailAppearance = this.depthFailAppearance; + var depthFailMaterial = defined(depthFailAppearance) ? depthFailAppearance.material : undefined; + + if (this._depthFailAppearance !== depthFailAppearance) { + this._depthFailAppearance = depthFailAppearance; + this._depthFailMaterial = depthFailMaterial; + createRS = true; + createSP = true; + } else if (this._depthFailMaterial !== depthFailMaterial) { + this._depthFailMaterial = depthFailMaterial; + createSP = true; + } + var translucent = this._appearance.isTranslucent(); if (this._translucent !== translucent) { this._translucent = translucent; diff --git a/Source/Shaders/CompositeOITFS.glsl b/Source/Shaders/CompositeOITFS.glsl index b2efbceba787..dbe6c46d5801 100644 --- a/Source/Shaders/CompositeOITFS.glsl +++ b/Source/Shaders/CompositeOITFS.glsl @@ -3,7 +3,7 @@ * - http://jcgt.org/published/0002/02/09/ * - http://casual-effects.blogspot.com/2014/03/weighted-blended-order-independent.html */ - + uniform sampler2D u_opaque; uniform sampler2D u_accumulation; uniform sampler2D u_revealage; @@ -15,12 +15,17 @@ void main() vec4 opaque = texture2D(u_opaque, v_textureCoordinates); vec4 accum = texture2D(u_accumulation, v_textureCoordinates); float r = texture2D(u_revealage, v_textureCoordinates).r; - + #ifdef MRT vec4 transparent = vec4(accum.rgb / clamp(r, 1e-4, 5e4), accum.a); #else vec4 transparent = vec4(accum.rgb / clamp(accum.a, 1e-4, 5e4), r); #endif - + gl_FragColor = (1.0 - transparent.a) * transparent + transparent.a * opaque; + + if (opaque != czm_backgroundColor) + { + gl_FragColor.a = 1.0; + } } diff --git a/Source/Shaders/PostProcessFilters/FXAA.glsl b/Source/Shaders/PostProcessFilters/FXAA.glsl index edd2b911e4be..09067f48970e 100644 --- a/Source/Shaders/PostProcessFilters/FXAA.glsl +++ b/Source/Shaders/PostProcessFilters/FXAA.glsl @@ -1,245 +1,21 @@ -/** - * @license - * Copyright (c) 2011 NVIDIA Corporation. All rights reserved. - * - * TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED - * *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS - * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT,IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA - * OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT, OR - * CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS - * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY - * OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, - * EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -/* -FXAA_PRESET - Choose compile-in knob preset 0-5. ------------------------------------------------------------------------------- -FXAA_EDGE_THRESHOLD - The minimum amount of local contrast required - to apply algorithm. - 1.0/3.0 - too little - 1.0/4.0 - good start - 1.0/8.0 - applies to more edges - 1.0/16.0 - overkill ------------------------------------------------------------------------------- -FXAA_EDGE_THRESHOLD_MIN - Trims the algorithm from processing darks. - Perf optimization. - 1.0/32.0 - visible limit (smaller isn't visible) - 1.0/16.0 - good compromise - 1.0/12.0 - upper limit (seeing artifacts) ------------------------------------------------------------------------------- -FXAA_SEARCH_STEPS - Maximum number of search steps for end of span. ------------------------------------------------------------------------------- -FXAA_SEARCH_THRESHOLD - Controls when to stop searching. - 1.0/4.0 - seems to be the best quality wise ------------------------------------------------------------------------------- -FXAA_SUBPIX_TRIM - Controls sub-pixel aliasing removal. - 1.0/2.0 - low removal - 1.0/3.0 - medium removal - 1.0/4.0 - default removal - 1.0/8.0 - high removal - 0.0 - complete removal ------------------------------------------------------------------------------- -FXAA_SUBPIX_CAP - Insures fine detail is not completely removed. - This is important for the transition of sub-pixel detail, - like fences and wires. - 3.0/4.0 - default (medium amount of filtering) - 7.0/8.0 - high amount of filtering - 1.0 - no capping of sub-pixel aliasing removal -*/ - -#ifndef FXAA_PRESET - #define FXAA_PRESET 3 -#endif -#if (FXAA_PRESET == 3) - #define FXAA_EDGE_THRESHOLD (1.0/8.0) - #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0) - #define FXAA_SEARCH_STEPS 16 - #define FXAA_SEARCH_THRESHOLD (1.0/4.0) - #define FXAA_SUBPIX_CAP (3.0/4.0) - #define FXAA_SUBPIX_TRIM (1.0/4.0) -#endif -#if (FXAA_PRESET == 4) - #define FXAA_EDGE_THRESHOLD (1.0/8.0) - #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0) - #define FXAA_SEARCH_STEPS 24 - #define FXAA_SEARCH_THRESHOLD (1.0/4.0) - #define FXAA_SUBPIX_CAP (3.0/4.0) - #define FXAA_SUBPIX_TRIM (1.0/4.0) -#endif -#if (FXAA_PRESET == 5) - #define FXAA_EDGE_THRESHOLD (1.0/8.0) - #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0) - #define FXAA_SEARCH_STEPS 32 - #define FXAA_SEARCH_THRESHOLD (1.0/4.0) - #define FXAA_SUBPIX_CAP (3.0/4.0) - #define FXAA_SUBPIX_TRIM (1.0/4.0) -#endif - -#define FXAA_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_SUBPIX_TRIM)) - -// Return the luma, the estimation of luminance from rgb inputs. -// This approximates luma using one FMA instruction, -// skipping normalization and tossing out blue. -// FxaaLuma() will range 0.0 to 2.963210702. -float FxaaLuma(vec3 rgb) { - return rgb.y * (0.587/0.299) + rgb.x; -} - -vec3 FxaaLerp3(vec3 a, vec3 b, float amountOfA) { - return (vec3(-amountOfA) * b) + ((a * vec3(amountOfA)) + b); -} - -vec4 FxaaTexOff(sampler2D tex, vec2 pos, ivec2 off, vec2 rcpFrame) { - float x = pos.x + float(off.x) * rcpFrame.x; - float y = pos.y + float(off.y) * rcpFrame.y; - return texture2D(tex, vec2(x, y)); -} - -// pos is the output of FxaaVertexShader interpolated across screen. -// xy -> actual texture position {0.0 to 1.0} -// rcpFrame should be a uniform equal to {1.0/frameWidth, 1.0/frameHeight} -vec3 FxaaPixelShader(vec2 pos, sampler2D tex, vec2 rcpFrame) -{ - vec3 rgbN = FxaaTexOff(tex, pos.xy, ivec2( 0,-1), rcpFrame).xyz; - vec3 rgbW = FxaaTexOff(tex, pos.xy, ivec2(-1, 0), rcpFrame).xyz; - vec3 rgbM = FxaaTexOff(tex, pos.xy, ivec2( 0, 0), rcpFrame).xyz; - vec3 rgbE = FxaaTexOff(tex, pos.xy, ivec2( 1, 0), rcpFrame).xyz; - vec3 rgbS = FxaaTexOff(tex, pos.xy, ivec2( 0, 1), rcpFrame).xyz; - - float lumaN = FxaaLuma(rgbN); - float lumaW = FxaaLuma(rgbW); - float lumaM = FxaaLuma(rgbM); - float lumaE = FxaaLuma(rgbE); - float lumaS = FxaaLuma(rgbS); - float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE))); - float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE))); - - float range = rangeMax - rangeMin; - if(range < max(FXAA_EDGE_THRESHOLD_MIN, rangeMax * FXAA_EDGE_THRESHOLD)) - { - return rgbM; - } - - vec3 rgbL = rgbN + rgbW + rgbM + rgbE + rgbS; - - float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25; - float rangeL = abs(lumaL - lumaM); - float blendL = max(0.0, (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE; - blendL = min(FXAA_SUBPIX_CAP, blendL); - - vec3 rgbNW = FxaaTexOff(tex, pos.xy, ivec2(-1,-1), rcpFrame).xyz; - vec3 rgbNE = FxaaTexOff(tex, pos.xy, ivec2( 1,-1), rcpFrame).xyz; - vec3 rgbSW = FxaaTexOff(tex, pos.xy, ivec2(-1, 1), rcpFrame).xyz; - vec3 rgbSE = FxaaTexOff(tex, pos.xy, ivec2( 1, 1), rcpFrame).xyz; - rgbL += (rgbNW + rgbNE + rgbSW + rgbSE); - rgbL *= vec3(1.0/9.0); - - float lumaNW = FxaaLuma(rgbNW); - float lumaNE = FxaaLuma(rgbNE); - float lumaSW = FxaaLuma(rgbSW); - float lumaSE = FxaaLuma(rgbSE); - - float edgeVert = - abs((0.25 * lumaNW) + (-0.5 * lumaN) + (0.25 * lumaNE)) + - abs((0.50 * lumaW ) + (-1.0 * lumaM) + (0.50 * lumaE )) + - abs((0.25 * lumaSW) + (-0.5 * lumaS) + (0.25 * lumaSE)); - float edgeHorz = - abs((0.25 * lumaNW) + (-0.5 * lumaW) + (0.25 * lumaSW)) + - abs((0.50 * lumaN ) + (-1.0 * lumaM) + (0.50 * lumaS )) + - abs((0.25 * lumaNE) + (-0.5 * lumaE) + (0.25 * lumaSE)); - - bool horzSpan = edgeHorz >= edgeVert; - float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x; - - if(!horzSpan) - { - lumaN = lumaW; - lumaS = lumaE; - } - - float gradientN = abs(lumaN - lumaM); - float gradientS = abs(lumaS - lumaM); - lumaN = (lumaN + lumaM) * 0.5; - lumaS = (lumaS + lumaM) * 0.5; - - if (gradientN < gradientS) - { - lumaN = lumaS; - lumaN = lumaS; - gradientN = gradientS; - lengthSign *= -1.0; - } - - vec2 posN; - posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5); - posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0); - - gradientN *= FXAA_SEARCH_THRESHOLD; - - vec2 posP = posN; - vec2 offNP = horzSpan ? vec2(rcpFrame.x, 0.0) : vec2(0.0, rcpFrame.y); - float lumaEndN = lumaN; - float lumaEndP = lumaN; - bool doneN = false; - bool doneP = false; - posN += offNP * vec2(-1.0, -1.0); - posP += offNP * vec2( 1.0, 1.0); - - for(int i = 0; i < FXAA_SEARCH_STEPS; i++) { - if(!doneN) - { - lumaEndN = FxaaLuma(texture2D(tex, posN.xy).xyz); - } - if(!doneP) - { - lumaEndP = FxaaLuma(texture2D(tex, posP.xy).xyz); - } - - doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN); - doneP = doneP || (abs(lumaEndP - lumaN) >= gradientN); - - if(doneN && doneP) - { - break; - } - if(!doneN) - { - posN -= offNP; - } - if(!doneP) - { - posP += offNP; - } - } - - float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y; - float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y; - bool directionN = dstN < dstP; - lumaEndN = directionN ? lumaEndN : lumaEndP; - - if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0)) - { - lengthSign = 0.0; - } - - - float spanLength = (dstP + dstN); - dstN = directionN ? dstN : dstP; - float subPixelOffset = (0.5 + (dstN * (-1.0/spanLength))) * lengthSign; - vec3 rgbF = texture2D(tex, vec2( - pos.x + (horzSpan ? 0.0 : subPixelOffset), - pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz; - return FxaaLerp3(rgbL, rgbF, blendL); -} +varying vec2 v_textureCoordinates; uniform sampler2D u_texture; -uniform vec2 u_step; +uniform vec2 u_fxaaQualityRcpFrame; -varying vec2 v_textureCoordinates; +const float fxaaQualitySubpix = 0.5; +const float fxaaQualityEdgeThreshold = 0.125; +const float fxaaQualityEdgeThresholdMin = 0.0833; void main() { - gl_FragColor = vec4(FxaaPixelShader(v_textureCoordinates, u_texture, u_step), 1.0); + vec4 color = FxaaPixelShader( + v_textureCoordinates, + u_texture, + u_fxaaQualityRcpFrame, + fxaaQualitySubpix, + fxaaQualityEdgeThreshold, + fxaaQualityEdgeThresholdMin); + float alpha = texture2D(u_texture, v_textureCoordinates).a; + gl_FragColor = vec4(color.rgb, alpha); } diff --git a/Source/ThirdParty/Shaders/FXAA3_11.glsl b/Source/ThirdParty/Shaders/FXAA3_11.glsl new file mode 100644 index 000000000000..3499e14f1cfa --- /dev/null +++ b/Source/ThirdParty/Shaders/FXAA3_11.glsl @@ -0,0 +1,648 @@ +/** + * @license + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of NVIDIA CORPORATION nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// NVIDIA GameWorks Graphics Samples GitHub link: https://github.com/NVIDIAGameWorks/GraphicsSamples +// Original FXAA 3.11 shader link: https://github.com/NVIDIAGameWorks/GraphicsSamples/blob/master/samples/es3-kepler/FXAA/FXAA3_11.h + +// Steps used to integrate into Cesium: +// * The following defines are set: +// #define FXAA_PC 1 +// #define FXAA_WEBGL_1 1 +// #define FXAA_GREEN_AS_LUMA 1 +// #define FXAA_EARLY_EXIT 1 +// #define FXAA_GLSL_120 1 +// * All other preprocessor directives besides the FXAA_QUALITY__P* directives were removed. +// * Double underscores are invalid for preprocessor directives so replace them with a single underscore. Replace +// /FXAA_QUALITY__P(.*)/g with /FXAA_QUALITY__P$1/. +// * There are no implicit conversions from ivec* to vec* so replace: +// #define FxaaInt2 ivec2 +// with +// #define FxaaInt2 vec2 +// * The texture2DLod function is only available in vertex shaders so replace: +// #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) +// #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) +// with +// #define FxaaTexTop(t, p) texture2D(t, p) +// #define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r)) +// * FXAA_QUALITY_PRESET is prepended in the javascript code. We may want to expose that setting in the future. +// * The following parameters to FxaaPixelShader are unused and can be removed: +// fxaaConsolePosPos +// fxaaConsoleRcpFrameOpt +// fxaaConsoleRcpFrameOpt2 +// fxaaConsole360RcpFrameOpt2 +// fxaaConsoleEdgeSharpness +// fxaaConsoleEdgeThreshold +// fxaaConsoleEdgeThresholdMi +// fxaaConsole360ConstDir + +// +// Choose the quality preset. +// This needs to be compiled into the shader as it effects code. +// Best option to include multiple presets is to +// in each shader define the preset, then include this file. +// +// OPTIONS +// ----------------------------------------------------------------------- +// 10 to 15 - default medium dither (10=fastest, 15=highest quality) +// 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) +// 39 - no dither, very expensive +// +// NOTES +// ----------------------------------------------------------------------- +// 12 = slightly faster then FXAA 3.9 and higher edge quality (default) +// 13 = about same speed as FXAA 3.9 and better than 12 +// 23 = closest to FXAA 3.9 visually and performance wise +// _ = the lowest digit is directly related to performance +// _ = the highest digit is directly related to style +// +//#define FXAA_QUALITY_PRESET 12 + + +#if (FXAA_QUALITY_PRESET == 10) + #define FXAA_QUALITY_PS 3 + #define FXAA_QUALITY_P0 1.5 + #define FXAA_QUALITY_P1 3.0 + #define FXAA_QUALITY_P2 12.0 +#endif +#if (FXAA_QUALITY_PRESET == 11) + #define FXAA_QUALITY_PS 4 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 3.0 + #define FXAA_QUALITY_P3 12.0 +#endif +#if (FXAA_QUALITY_PRESET == 12) + #define FXAA_QUALITY_PS 5 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 4.0 + #define FXAA_QUALITY_P4 12.0 +#endif +#if (FXAA_QUALITY_PRESET == 13) + #define FXAA_QUALITY_PS 6 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 4.0 + #define FXAA_QUALITY_P5 12.0 +#endif +#if (FXAA_QUALITY_PRESET == 14) + #define FXAA_QUALITY_PS 7 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 4.0 + #define FXAA_QUALITY_P6 12.0 +#endif +#if (FXAA_QUALITY_PRESET == 15) + #define FXAA_QUALITY_PS 8 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 4.0 + #define FXAA_QUALITY_P7 12.0 +#endif +#if (FXAA_QUALITY_PRESET == 20) + #define FXAA_QUALITY_PS 3 + #define FXAA_QUALITY_P0 1.5 + #define FXAA_QUALITY_P1 2.0 + #define FXAA_QUALITY_P2 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 21) + #define FXAA_QUALITY_PS 4 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 22) + #define FXAA_QUALITY_PS 5 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 23) + #define FXAA_QUALITY_PS 6 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 24) + #define FXAA_QUALITY_PS 7 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 3.0 + #define FXAA_QUALITY_P6 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 25) + #define FXAA_QUALITY_PS 8 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 4.0 + #define FXAA_QUALITY_P7 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 26) + #define FXAA_QUALITY_PS 9 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 4.0 + #define FXAA_QUALITY_P8 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 27) + #define FXAA_QUALITY_PS 10 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 4.0 + #define FXAA_QUALITY_P9 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 28) + #define FXAA_QUALITY_PS 11 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 2.0 + #define FXAA_QUALITY_P9 4.0 + #define FXAA_QUALITY_P10 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 29) + #define FXAA_QUALITY_PS 12 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 2.0 + #define FXAA_QUALITY_P9 2.0 + #define FXAA_QUALITY_P10 4.0 + #define FXAA_QUALITY_P11 8.0 +#endif +#if (FXAA_QUALITY_PRESET == 39) + #define FXAA_QUALITY_PS 12 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.0 + #define FXAA_QUALITY_P2 1.0 + #define FXAA_QUALITY_P3 1.0 + #define FXAA_QUALITY_P4 1.0 + #define FXAA_QUALITY_P5 1.5 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 2.0 + #define FXAA_QUALITY_P9 2.0 + #define FXAA_QUALITY_P10 4.0 + #define FXAA_QUALITY_P11 8.0 +#endif + +#define FxaaBool bool +#define FxaaFloat float +#define FxaaFloat2 vec2 +#define FxaaFloat3 vec3 +#define FxaaFloat4 vec4 +#define FxaaHalf float +#define FxaaHalf2 vec2 +#define FxaaHalf3 vec3 +#define FxaaHalf4 vec4 +#define FxaaInt2 vec2 +#define FxaaTex sampler2D + +#define FxaaSat(x) clamp(x, 0.0, 1.0) +#define FxaaTexTop(t, p) texture2D(t, p) +#define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r)) + +FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } + +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #define lumaM rgbyM.y + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY_P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY_P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY_P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY_P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); +} diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index 285d295be647..9157d46e4aab 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -22,6 +22,8 @@ defineSuite([ 'DataSources/StaticGeometryPerMaterialBatch', 'DataSources/StaticGroundGeometryColorBatch', 'DataSources/StaticOutlineGeometryBatch', + 'DataSources/PolylineGeometryUpdater', + 'DataSources/PolylineGraphics', 'Scene/GroundPrimitive', 'Scene/ShadowMode', 'Specs/createDynamicProperty', @@ -50,6 +52,8 @@ defineSuite([ StaticGeometryPerMaterialBatch, StaticGroundGeometryColorBatch, StaticOutlineGeometryBatch, + PolylineGeometryUpdater, + PolylineGraphics, GroundPrimitive, ShadowMode, createDynamicProperty, @@ -348,6 +352,174 @@ defineSuite([ return createAndRemoveGeometryWithShadows(ShadowMode.RECEIVE_ONLY); }); + it('Creates and removes static color material and static color depth fail material', function() { + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(PolylineGeometryUpdater, scene, objects); + + var polyline = new PolylineGraphics(); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.material = new ColorMaterialProperty(); + polyline.depthFailMaterial = new ColorMaterialProperty(); + + var entity = new Entity(); + entity.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity.polyline = polyline; + objects.add(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + var primitive = scene.primitives.get(0); + var attributes = primitive.getGeometryInstanceAttributes(entity); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.WHITE)); + expect(attributes.depthFailColor).toEqual(ColorGeometryInstanceAttribute.toValue(Color.WHITE)); + expect(primitive.appearance).toBeInstanceOf(PolylineGeometryUpdater.perInstanceColorAppearanceType); + expect(primitive.depthFailAppearance).toBeInstanceOf(PolylineGeometryUpdater.perInstanceColorAppearanceType); + + objects.remove(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0; + }).then(function(){ + visualizer.destroy(); + }); + }); + }); + + it('Creates and removes static color material and static depth fail material', function() { + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(PolylineGeometryUpdater, scene, objects); + + var polyline = new PolylineGraphics(); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.material = new ColorMaterialProperty(); + polyline.depthFailMaterial = new GridMaterialProperty(); + + var entity = new Entity(); + entity.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity.polyline = polyline; + objects.add(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + var primitive = scene.primitives.get(0); + var attributes = primitive.getGeometryInstanceAttributes(entity); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.WHITE)); + expect(attributes.depthFailColor).toBeUndefined(); + expect(primitive.appearance).toBeInstanceOf(PolylineGeometryUpdater.perInstanceColorAppearanceType); + expect(primitive.depthFailAppearance).toBeInstanceOf(PolylineGeometryUpdater.materialAppearanceType); + + objects.remove(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0; + }).then(function(){ + visualizer.destroy(); + }); + }); + }); + + it('Creates and removes static material and static depth fail material', function() { + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(PolylineGeometryUpdater, scene, objects); + + var polyline = new PolylineGraphics(); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.material = new GridMaterialProperty(); + polyline.depthFailMaterial = new GridMaterialProperty(); + + var entity = new Entity(); + entity.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity.polyline = polyline; + objects.add(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + var primitive = scene.primitives.get(0); + var attributes = primitive.getGeometryInstanceAttributes(entity); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toBeUndefined(); + expect(attributes.depthFailColor).toBeUndefined(); + expect(primitive.appearance).toBeInstanceOf(PolylineGeometryUpdater.materialAppearanceType); + expect(primitive.depthFailAppearance).toBeInstanceOf(PolylineGeometryUpdater.materialAppearanceType); + + objects.remove(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0; + }).then(function(){ + visualizer.destroy(); + }); + }); + }); + + it('Creates and removes static material and static color depth fail material', function() { + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(PolylineGeometryUpdater, scene, objects); + + var polyline = new PolylineGraphics(); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.material = new GridMaterialProperty(); + polyline.depthFailMaterial = new ColorMaterialProperty(); + + var entity = new Entity(); + entity.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity.polyline = polyline; + objects.add(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + var primitive = scene.primitives.get(0); + var attributes = primitive.getGeometryInstanceAttributes(entity); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toBeUndefined(); + expect(attributes.depthFailColor).toEqual(ColorGeometryInstanceAttribute.toValue(Color.WHITE)); + expect(primitive.appearance).toBeInstanceOf(PolylineGeometryUpdater.materialAppearanceType); + expect(primitive.depthFailAppearance).toBeInstanceOf(PolylineGeometryUpdater.perInstanceColorAppearanceType); + + objects.remove(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0; + }).then(function(){ + visualizer.destroy(); + }); + }); + }); + it('Correctly handles geometry changing batches', function() { var objects = new EntityCollection(); var visualizer = new GeometryVisualizer(EllipseGeometryUpdater, scene, objects); @@ -533,7 +705,7 @@ defineSuite([ }); it('StaticGeometryPerMaterialBatch handles shared material being invalidated', function() { - var batch = new StaticGeometryPerMaterialBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, false, ShadowMode.DISABLED); + var batch = new StaticGeometryPerMaterialBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, undefined, false, ShadowMode.DISABLED); var ellipse = new EllipseGraphics(); ellipse.semiMajorAxis = new ConstantProperty(2); @@ -580,7 +752,7 @@ defineSuite([ }); it('StaticGeometryColorBatch updates color attribute after rebuilding primitive', function() { - var batch = new StaticGeometryColorBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, false, ShadowMode.DISABLED); + var batch = new StaticGeometryColorBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, undefined, false, ShadowMode.DISABLED); var entity = new Entity({ position : new Cartesian3(1234, 5678, 9101112), diff --git a/Specs/DataSources/PolylineGeometryUpdaterSpec.js b/Specs/DataSources/PolylineGeometryUpdaterSpec.js index 5dc3db3d66ef..2b871c8371ba 100644 --- a/Specs/DataSources/PolylineGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolylineGeometryUpdaterSpec.js @@ -91,6 +91,7 @@ defineSuite([ expect(updater.isClosed).toBe(false); expect(updater.fillEnabled).toBe(false); expect(updater.fillMaterialProperty).toBe(undefined); + expect(updater.depthFailMaterialProperty).toBe(undefined); expect(updater.outlineEnabled).toBe(false); expect(updater.hasConstantFill).toBe(true); expect(updater.hasConstantOutline).toBe(true); @@ -131,6 +132,7 @@ defineSuite([ expect(updater.isClosed).toBe(false); expect(updater.fillEnabled).toBe(true); expect(updater.fillMaterialProperty).toEqual(new ColorMaterialProperty(Color.WHITE)); + expect(updater.depthFailMaterialProperty).toBe(undefined); expect(updater.outlineEnabled).toBe(false); expect(updater.hasConstantFill).toBe(true); expect(updater.hasConstantOutline).toBe(true); @@ -147,6 +149,13 @@ defineSuite([ expect(updater.fillMaterialProperty).toBe(entity.polyline.material); }); + it('Polyline depth fail material is correctly exposed.', function() { + var entity = createBasicPolyline(); + var updater = new PolylineGeometryUpdater(entity, scene); + entity.polyline.depthFailMaterial = new ColorMaterialProperty(); + expect(updater.depthFailMaterialProperty).toBe(entity.polyline.depthFailMaterial); + }); + it('A time-varying positions causes geometry to be dynamic', function() { var entity = createBasicPolyline(); var updater = new PolylineGeometryUpdater(entity, scene); @@ -198,6 +207,7 @@ defineSuite([ var polyline = entity.polyline; polyline.show = new ConstantProperty(options.show); polyline.material = options.material; + polyline.depthFailMaterial = options.depthFailMaterial; polyline.width = new ConstantProperty(options.width); polyline.followSurface = new ConstantProperty(options.followSurface); @@ -221,6 +231,11 @@ defineSuite([ } else { expect(attributes.color).toBeUndefined(); } + if (options.depthFailMaterial && options.depthFailMaterial instanceof ColorMaterialProperty) { + expect(attributes.depthFailColor.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.depthFailMaterial.color.getValue(time))); + } else { + expect(attributes.depthFailColor).toBeUndefined(); + } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.show)); if (options.distanceDisplayCondition) { expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); @@ -237,6 +252,28 @@ defineSuite([ }); }); + it('Creates expected per-color geometry with color depth fail appearance', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + depthFailMaterial : new ColorMaterialProperty(Color.BLUE), + width : 3, + followSurface : false, + granularity : 1.0 + }); + }); + + it('Creates expected per-color geometry with material depth fail appearance', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + depthFailMaterial : new GridMaterialProperty(), + width : 3, + followSurface : false, + granularity : 1.0 + }); + }); + it('Creates expected per-material geometry', function() { validateGeometryInstance({ show : true, @@ -247,6 +284,28 @@ defineSuite([ }); }); + it('Creates expected per-material geometry with color depth fail appearance', function() { + validateGeometryInstance({ + show : true, + material : new GridMaterialProperty(), + depthFailMaterial : new ColorMaterialProperty(Color.BLUE), + width : 4, + followSurface : true, + granularity : 0.5 + }); + }); + + it('Creates expected per-material geometry with color depth fail appearance', function() { + validateGeometryInstance({ + show : true, + material : new GridMaterialProperty(), + depthFailMaterial : new GridMaterialProperty(), + width : 4, + followSurface : true, + granularity : 0.5 + }); + }); + it('Creates expected distance display condition geometry', function() { validateGeometryInstance({ show : true, diff --git a/Specs/DataSources/PolylineGraphicsSpec.js b/Specs/DataSources/PolylineGraphicsSpec.js index 4e303b179e35..a41a146c47dd 100644 --- a/Specs/DataSources/PolylineGraphicsSpec.js +++ b/Specs/DataSources/PolylineGraphicsSpec.js @@ -22,6 +22,7 @@ defineSuite([ it('creates expected instance from raw assignment and construction', function() { var options = { material : Color.BLUE, + depthFailMaterial : Color.RED, positions : [], show : true, width : 1, @@ -33,6 +34,7 @@ defineSuite([ var polyline = new PolylineGraphics(options); expect(polyline.material).toBeInstanceOf(ColorMaterialProperty); + expect(polyline.depthFailMaterial).toBeInstanceOf(ColorMaterialProperty); expect(polyline.positions).toBeInstanceOf(ConstantProperty); expect(polyline.show).toBeInstanceOf(ConstantProperty); expect(polyline.width).toBeInstanceOf(ConstantProperty); @@ -42,6 +44,7 @@ defineSuite([ expect(polyline.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(polyline.material.color.getValue()).toEqual(options.material); + expect(polyline.depthFailMaterial.color.getValue()).toEqual(options.depthFailMaterial); expect(polyline.positions.getValue()).toEqual(options.positions); expect(polyline.show.getValue()).toEqual(options.show); expect(polyline.width.getValue()).toEqual(options.width); @@ -54,6 +57,7 @@ defineSuite([ it('merge assigns unassigned properties', function() { var source = new PolylineGraphics(); source.material = new ColorMaterialProperty(); + source.depthFailMaterial = new ColorMaterialProperty(); source.positions = new ConstantProperty(); source.width = new ConstantProperty(); source.show = new ConstantProperty(); @@ -65,6 +69,7 @@ defineSuite([ var target = new PolylineGraphics(); target.merge(source); expect(target.material).toBe(source.material); + expect(target.depthFailMaterial).toBe(source.depthFailMaterial); expect(target.positions).toBe(source.positions); expect(target.width).toBe(source.width); expect(target.show).toBe(source.show); @@ -77,6 +82,7 @@ defineSuite([ it('merge does not assign assigned properties', function() { var source = new PolylineGraphics(); source.material = new ColorMaterialProperty(); + source.depthFailMaterial = new ColorMaterialProperty(); source.positions = new ConstantProperty(); source.width = new ConstantProperty(); source.show = new ConstantProperty(); @@ -86,6 +92,7 @@ defineSuite([ source.distanceDisplayCondition = new ConstantProperty(); var color = new ColorMaterialProperty(); + var depthFailColor = new ColorMaterialProperty(); var positions = new ConstantProperty(); var width = new ConstantProperty(); var show = new ConstantProperty(); @@ -96,6 +103,7 @@ defineSuite([ var target = new PolylineGraphics(); target.material = color; + target.depthFailMaterial = depthFailColor; target.positions = positions; target.width = width; target.show = show; @@ -106,6 +114,7 @@ defineSuite([ target.merge(source); expect(target.material).toBe(color); + expect(target.depthFailMaterial).toBe(depthFailColor); expect(target.positions).toBe(positions); expect(target.width).toBe(width); expect(target.show).toBe(show); @@ -118,6 +127,7 @@ defineSuite([ it('clone works', function() { var source = new PolylineGraphics(); source.material = new ColorMaterialProperty(); + source.depthFailMaterial = new ColorMaterialProperty(); source.width = new ConstantProperty(); source.positions = new ConstantProperty(); source.show = new ConstantProperty(); @@ -128,6 +138,7 @@ defineSuite([ var result = source.clone(); expect(result.material).toBe(source.material); + expect(result.depthFailMaterial).toBe(source.depthFailMaterial); expect(result.positions).toBe(source.positions); expect(result.width).toBe(source.width); expect(result.show).toBe(source.show); @@ -147,6 +158,7 @@ defineSuite([ it('raises definitionChanged when a property is assigned or modified', function() { var property = new PolylineGraphics(); testMaterialDefinitionChanged(property, 'material', Color.RED, Color.BLUE); + testMaterialDefinitionChanged(property, 'depthFailMaterial', Color.RED, Color.BLUE); testDefinitionChanged(property, 'show', true, false); testDefinitionChanged(property, 'positions', [], []); testDefinitionChanged(property, 'width', 3, 4); diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index ca981609044b..69e6faa53780 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -156,6 +156,7 @@ defineSuite([ primitive = new Primitive(); expect(primitive.geometryInstances).not.toBeDefined(); expect(primitive.appearance).not.toBeDefined(); + expect(primitive.depthFailAppearance).not.toBeDefined(); expect(primitive.modelMatrix).toEqual(Matrix4.IDENTITY); expect(primitive.show).toEqual(true); expect(primitive.vertexCacheOptimize).toEqual(false); @@ -171,11 +172,13 @@ defineSuite([ it('Constructs with options', function() { var geometryInstances = {}; var appearance = {}; + var depthFailAppearance = {}; var modelMatrix = Matrix4.fromUniformScale(5.0); primitive = new Primitive({ geometryInstances : geometryInstances, appearance : appearance, + depthFailAppearance : depthFailAppearance, modelMatrix : modelMatrix, show : false, vertexCacheOptimize : true, @@ -190,6 +193,7 @@ defineSuite([ expect(primitive.geometryInstances).toEqual(geometryInstances); expect(primitive.appearance).toEqual(appearance); + expect(primitive.depthFailAppearance).toEqual(depthFailAppearance); expect(primitive.modelMatrix).toEqual(modelMatrix); expect(primitive.show).toEqual(false); expect(primitive.vertexCacheOptimize).toEqual(true); @@ -433,6 +437,60 @@ defineSuite([ scene._camera = camera; }); + it('renders with depth fail appearance', function() { + var rect = Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0); + var translation = Cartesian3.multiplyByScalar(Cartesian3.normalize(ellipsoid.cartographicToCartesian(Rectangle.center(rect)), new Cartesian3()), 100.0, new Cartesian3()); + var rectInstance = new GeometryInstance({ + geometry : new RectangleGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + rectangle : rect + }), + modelMatrix : Matrix4.fromTranslation(translation, new Matrix4()), + id : 'rect', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + var p0 = new Primitive({ + geometryInstances : rectInstance, + appearance : new PerInstanceColorAppearance({ + translucent : false + }), + asynchronous : false + }); + + var rectInstance2 = new GeometryInstance({ + geometry : new RectangleGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + rectangle : rect + }), + id : 'rect2', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 1.0), + depthFailColor : new ColorGeometryInstanceAttribute(1.0, 0.0, 1.0, 1.0) + } + }); + var p1 = new Primitive({ + geometryInstances : rectInstance2, + appearance : new PerInstanceColorAppearance({ + translucent : false + }), + depthFailAppearance : new PerInstanceColorAppearance({ + translucent : false + }), + asynchronous : false + }); + + scene.primitives.add(p0); + scene.primitives.add(p1); + scene.camera.setView({ destination : rect }); + scene.renderForSpecs(); + + expect(scene).toRender([255, 0, 255, 255]); + }); + it('RTC throws with more than one instance', function() { expect(function() { return new Primitive({ diff --git a/gulpfile.js b/gulpfile.js index 45a2f61da48c..13be1624c703 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -81,6 +81,7 @@ var filesToClean = ['Source/Cesium.js', 'Build', 'Instrumented', 'Source/Shaders/**/*.js', + 'Source/ThirdParty/Shaders/*.js', 'Specs/SpecList.js', 'Apps/Sandcastle/jsHintOptions.js', 'Apps/Sandcastle/gallery/gallery-index.js', @@ -957,7 +958,7 @@ function glslToJavaScript(minify, minifyStateFilePath) { // we still are using from the set, then delete any files remaining in the set. var leftOverJsFiles = {}; - globby.sync(['Source/Shaders/**/*.js']).forEach(function(file) { + globby.sync(['Source/Shaders/**/*.js', 'Source/ThirdParty/Shaders/*.js']).forEach(function(file) { leftOverJsFiles[path.normalize(file)] = true; }); @@ -965,7 +966,7 @@ function glslToJavaScript(minify, minifyStateFilePath) { var builtinConstants = []; var builtinStructs = []; - var glslFiles = globby.sync(['Source/Shaders/**/*.glsl']); + var glslFiles = globby.sync(['Source/Shaders/**/*.glsl', 'Source/ThirdParty/Shaders/*.glsl']); glslFiles.forEach(function(glslFile) { glslFile = path.normalize(glslFile); var baseName = path.basename(glslFile, '.glsl'); diff --git a/package.json b/package.json index e575d77ccd27..c3e5a93b3127 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "gulp-jshint": "^2.0.4", "gulp-rename": "^1.2.2", "gulp-replace": "^0.5.4", - "gulp-tap": "^0.1.3", + "gulp-tap": "^0.4.1", "gulp-zip": "^4.0.0", "jasmine-core": "^2.5.2", "jsdoc": "^3.4.3", diff --git a/server.js b/server.js index 6b6eca4c3767..5b8b5be287b1 100644 --- a/server.js +++ b/server.js @@ -42,8 +42,8 @@ 'application/json' : ['czml', 'json', 'geojson', 'topojson'], 'image/crn' : ['crn'], 'image/ktx' : ['ktx'], - 'model/vnd.gltf+json' : ['gltf'], - 'model/vnd.gltf.binary' : ['bgltf', 'glb'], + 'model/gltf+json' : ['gltf'], + 'model/gltf.binary' : ['bgltf', 'glb'], 'text/plain' : ['glsl'] }); diff --git a/web.config b/web.config index fcc9ea104a62..78ae51dd8fce 100644 --- a/web.config +++ b/web.config @@ -7,11 +7,11 @@ - + - + - +