From f9bf08c5ae95477f1546752d9808ca86f28650eb Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 1 Oct 2013 09:40:51 -0400 Subject: [PATCH 01/10] Initial commit for issue #1076. Added translucencyByDistance to billboard and incorporated into Label. SandCastle examples added for both label and billboard fading based on camera distance. Signed-off-by: Alex Wood --- Apps/Sandcastle/gallery/Billboards.html | 30 ++++++++++ Apps/Sandcastle/gallery/Labels.html | 39 +++++++++++++ Source/DynamicScene/DynamicBillboard.js | 1 + Source/Scene/Billboard.js | 65 +++++++++++++++++++++- Source/Scene/BillboardCollection.js | 68 ++++++++++++++++++++--- Source/Scene/Label.js | 53 +++++++++++++++++- Source/Scene/LabelCollection.js | 1 + Source/Shaders/BillboardCollectionVS.glsl | 41 +++++++++----- 8 files changed, 274 insertions(+), 24 deletions(-) diff --git a/Apps/Sandcastle/gallery/Billboards.html b/Apps/Sandcastle/gallery/Billboards.html index 6b458e698e51..53102c78e49b 100644 --- a/Apps/Sandcastle/gallery/Billboards.html +++ b/Apps/Sandcastle/gallery/Billboards.html @@ -162,6 +162,26 @@ image.src = '../images/facility.gif'; } + function billboardTranslucencyByDistance(scene, ellipsoid) { + Sandcastle.declare(billboardTranslucencyByDistance); // For highlighting in Sandcastle. + var image = new Image(); + image.onload = function() { + var billboards = new Cesium.BillboardCollection(); + var textureAtlas = scene.getContext().createTextureAtlas({ + image : image + }); + billboards.setTextureAtlas(textureAtlas); + + billboards.add({ + position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.59777, 40.03883)), + imageIndex : 0, + translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.2) + }); + scene.getPrimitives().add(billboards); + }; + image.src = '../images/Cesium_Logo_overlay.gif'; + } + function addPointBillboards(scene, ellipsoid) { Sandcastle.declare(addPointBillboards); // For highlighting in Sandcastle. // A white circle is drawn into a 2D canvas. The canvas is used as @@ -430,6 +450,16 @@ }; button.textContent = 'Scale by viewer distance'; toolbar.appendChild(button); + + button = document.createElement('button'); + button.className = 'cesium-button'; + button.onclick = function() { + primitives.removeAll(); + billboardTranslucencyByDistance(scene, ellipsoid); + Sandcastle.highlight(billboardTranslucencyByDistance); + }; + button.textContent = 'Fade by viewer distance'; + toolbar.appendChild(button); } var widget = new Cesium.CesiumWidget('cesiumContainer'); diff --git a/Apps/Sandcastle/gallery/Labels.html b/Apps/Sandcastle/gallery/Labels.html index 012d87530a30..ef2df1a47dc6 100644 --- a/Apps/Sandcastle/gallery/Labels.html +++ b/Apps/Sandcastle/gallery/Labels.html @@ -90,6 +90,35 @@ scene.getPrimitives().add(labels); } + function labelTranslucencyByDistance(scene, ellipsoid) { + Sandcastle.declare(labelTranslucencyByDistance); // For highlighting in Sandcastle. + var labels = new Cesium.LabelCollection(); + var l = labels.add({ + position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.10, 39.57)), + text : 'Philadelphia', + translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.0), + pixelOffset : new Cesium.Cartesian2(0, 50) + }); + + var image = new Image(); + image.onload = function() { + var billboards = new Cesium.BillboardCollection(); + var textureAtlas = scene.getContext().createTextureAtlas({ + image : image + }); + billboards.setTextureAtlas(textureAtlas); + + billboards.add({ + position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.10, 39.57)), + imageIndex : 0 + }); + scene.getPrimitives().add(billboards); + }; + image.src = '../images/facility.gif'; + + scene.getPrimitives().add(labels); + } + function createButtons(widget) { var ellipsoid = widget.centralBody.getEllipsoid(); var scene = widget.scene; @@ -135,6 +164,16 @@ }; button.textContent = 'Add labels in reference frame'; toolbar.appendChild(button); + + button = document.createElement('button'); + button.className = 'cesium-button'; + button.onclick = function() { + primitives.removeAll(); + labelTranslucencyByDistance(scene, ellipsoid); + Sandcastle.highlight(labelTranslucencyByDistance); + }; + button.textContent = 'Fade label by distance'; + toolbar.appendChild(button); } var widget = new Cesium.CesiumWidget('cesiumContainer'); diff --git a/Source/DynamicScene/DynamicBillboard.js b/Source/DynamicScene/DynamicBillboard.js index 3cef308b7664..e8465da28021 100644 --- a/Source/DynamicScene/DynamicBillboard.js +++ b/Source/DynamicScene/DynamicBillboard.js @@ -33,6 +33,7 @@ define(['../Core/defaultValue', this._eyeOffset = undefined; this._pixelOffset = undefined; this._show = undefined; + this._nearFarScalar = undefined; this._propertyChanged = new Event(); }; diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index f06ece931fcb..9ce41fde3e96 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -51,6 +51,7 @@ define([ * and add new billboards instead of modifying each one. * * @exception {DeveloperError} scaleByDistance.far must be greater than scaleByDistance.near + * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near * * @see BillboardCollection * @see BillboardCollection#add @@ -66,6 +67,10 @@ define([ if (defined(description.scaleByDistance) && description.scaleByDistance.far <= description.scaleByDistance.near) { throw new DeveloperError('scaleByDistance.far must be greater than scaleByDistance.near.'); } + if (defined(description.translucencyByDistance) && + description.translucencyByDistance.far <= description.translucencyByDistance.near) { + throw new DeveloperError('translucencyByDistance.far must be greater than translucencyByDistance.near.'); + } this._show = defaultValue(description.show, true); @@ -84,6 +89,7 @@ define([ this._width = description.width; this._height = description.height; this._scaleByDistance = description.scaleByDistance; + this._translucencyByDistance = description.translucencyByDistance; this._pickId = undefined; this._pickIdThis = description._pickIdThis; @@ -104,7 +110,8 @@ define([ var ROTATION_INDEX = Billboard.ROTATION_INDEX = 9; var ALIGNED_AXIS_INDEX = Billboard.ALIGNED_AXIS_INDEX = 10; var SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX = 11; - Billboard.NUMBER_OF_PROPERTIES = 12; + var TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX = 12; + Billboard.NUMBER_OF_PROPERTIES = 13; function makeDirty(billboard, propertyChanged) { var billboardCollection = billboard._billboardCollection; @@ -330,6 +337,59 @@ define([ this._scaleByDistance = NearFarScalar.clone(scale, this._scaleByDistance); }; + /** + * Returns the near and far translucency properties of a Billboard based on the billboard's distance from the camera. + * + * @memberof Billboard + * + * @returns {NearFarScalar} The near/far translucency values based on camera distance to the billboard + * + * @see Billboard#setTranslucencyByDistance + */ + Billboard.prototype.getTranslucencyByDistance = function() { + return this._translucencyByDistance; + }; + + /** + * Sets near and far translucency properties of a Billboard based on the billboard's distance from the camera. + * A billboard's translucency will interpolate between the {@link NearFarScalar#nearValue} and + * {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds + * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}. + * Outside of these ranges the billboard's translucency remains clamped to the nearest bound. If undefined, + * translucencyByDistance will be disabled. + * + * @memberof Billboard + * + * @param {NearFarScalar} translucency The configuration of near and far distances and their respective translucency values + * + * @exception {DeveloperError} far distance must be greater than near distance. + * + * @see Billboard#getTranslucencyByDistance + * + * @example + * // Example 1. + * // Set a billboard's translucencyByDistance to 1.0 when the + * // camera is 1500 meters from the billboard and disappear as + * // the camera distance approaches 8.0e6 meters. + * b.setTranslucencyByDistance(new NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0)); + * + * // Example 2. + * // disable translucency by distance + * b.setTranslucencyByDistance(undefined); + */ + Billboard.prototype.setTranslucencyByDistance = function(translucency) { + if (NearFarScalar.equals(this._translucencyByDistance, translucency)) { + return; + } + + if (translucency.far <= translucency.near) { + throw new DeveloperError('far distance must be greater than near distance.'); + } + + makeDirty(this, TRANSLUCENCY_BY_DISTANCE_INDEX); + this._translucencyByDistance = NearFarScalar.clone(translucency, this._translucencyByDistance); + }; + /** * Returns the 3D Cartesian offset applied to this billboard in eye coordinates. * @@ -886,7 +946,8 @@ define([ Color.equals(this._color, other._color) && Cartesian2.equals(this._pixelOffset, other._pixelOffset) && Cartesian3.equals(this._eyeOffset, other._eyeOffset) && - NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance); + NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) && + NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance); }; Billboard.prototype._destroy = function() { diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index 5e25781bf0da..09f8fd0782e0 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -63,6 +63,7 @@ define([ var ROTATION_INDEX = Billboard.ROTATION_INDEX; var ALIGNED_AXIS_INDEX = Billboard.ALIGNED_AXIS_INDEX; var SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX; + var TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX; var NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES; // PERFORMANCE_IDEA: Use vertex compression so we don't run out of @@ -78,7 +79,8 @@ define([ pickColor : 7, // pickColor and color shared an index because pickColor is only used during color : 7, // the 'pick' pass and 'color' is only used during the 'color' pass. rotationAndAlignedAxis : 8, - scaleByDistance : 9 + scaleByDistance : 9, + translucencyByDistance : 10 }; // Identifies to the VertexArrayFacade the attributes that are used only for the pick @@ -156,6 +158,10 @@ define([ this._compiledShaderScaleByDistance = false; this._compiledShaderScaleByDistancePick = false; + this._shaderTranslucencyByDistance = false; + this._compiledShaderTranslucencyByDistance = false; + this._compiledShaderTranslucencyByDistancePick = false; + this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES); this._maxSize = 0.0; @@ -213,7 +219,8 @@ define([ BufferUsage.STATIC_DRAW, // COLOR_INDEX BufferUsage.STATIC_DRAW, // ROTATION_INDEX BufferUsage.STATIC_DRAW, // ALIGNED_AXIS_INDEX - BufferUsage.STATIC_DRAW // SCALE_BY_DISTANCE_INDEX + BufferUsage.STATIC_DRAW, // SCALE_BY_DISTANCE_INDEX + BufferUsage.STATIC_DRAW // TRANSLUCENCY_BY_DISTANCE_INDEX ]; var that = this; @@ -256,6 +263,7 @@ define([ * verticalOrigin : VerticalOrigin.CENTER, * scale : 1.0, * scaleByDistance : new NearFarScalar(5e6, 1.0, 2e7, 0.0), + * translucencyByDistance : new NearFarScalar(5e6, 1.0, 2e7, 0.0), * imageIndex : 0, * color : Color.WHITE * }); @@ -685,6 +693,11 @@ define([ componentsPerAttribute : 4, componentDatatype : ComponentDatatype.FLOAT, usage : buffersUsage[SCALE_BY_DISTANCE_INDEX] + }, { + index : attributeIndices.translucencyByDistance, + componentsPerAttribute : 4, + componentDatatype : ComponentDatatype.FLOAT, + usage : buffersUsage[TRANSLUCENCY_BY_DISTANCE_INDEX] }], 4 * numberOfBillboards); // 4 vertices per billboard } @@ -893,6 +906,35 @@ define([ writer(i + 3, near, nearValue, far, farValue); } + function writeTranslucencyByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) { + var i = billboard._index * 4; + var allPurposeWriters = vafWriters[allPassPurpose]; + var writer = allPurposeWriters[attributeIndices.translucencyByDistance]; + var near = 0.0; + var nearValue = 0.0; + var far = 0.0; + var farValue = 0.0; + + var translucency = billboard.getTranslucencyByDistance(); + if (defined(translucency)) { + near = translucency.near; + nearValue = translucency.nearValue; + far = translucency.far; + farValue = translucency.farValue; + + if (nearValue !== 1.0 || farValue !== 1.0) { + // translucency by distance calculation in shader need not be enabled + // until a billboard with near and far !== 1.0 is found + billboardCollection._shaderTranslucencyByDistance = true; + } + } + + writer(i + 0, near, nearValue, far, farValue); + writer(i + 1, near, nearValue, far, farValue); + writer(i + 2, near, nearValue, far, farValue); + writer(i + 3, near, nearValue, far, farValue); + } + function writeBillboard(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) { writePosition(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); writePixelOffset(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); @@ -903,6 +945,7 @@ define([ writeTextureCoordinatesAndImageSize(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); writeRotationAndAlignedAxis(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); writeScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); + writeTranslucencyByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); } function recomputeActualPositions(billboardCollection, billboards, length, frameState, modelMatrix, recomputeBoundingVolume) { @@ -1091,6 +1134,10 @@ define([ writers.push(writeScaleByDistance); } + if (properties[TRANSLUCENCY_BY_DISTANCE_INDEX]) { + writers.push(writeTranslucencyByDistance); + } + vafWriters = this._vaf.writers; if ((billboardsToUpdateLength / billboardsLength) > 0.1) { @@ -1165,19 +1212,23 @@ define([ }); } - if (!defined(this._sp) || (this._shaderRotation && !this._compiledShaderRotation) || - (this._shaderScaleByDistance && !this._compiledShaderScaleByDistance)) { + if (!defined(this._sp) || + (this._shaderRotation && !this._compiledShaderRotation) || + (this._shaderScaleByDistance && !this._compiledShaderScaleByDistance) || + (this._shaderTranslucencyByDistance && !this._compiledShaderTranslucencyByDistance)) { this._sp = context.getShaderCache().replaceShaderProgram( this._sp, createShaderSource({ defines : [this._shaderRotation ? 'ROTATION' : '', - this._shaderScaleByDistance ? 'EYE_DISTANCE_SCALING' : ''], + this._shaderScaleByDistance ? 'EYE_DISTANCE_SCALING' : '', + this._shaderTranslucencyByDistance ? 'EYE_DISTANCE_TRANSLUCENCY' : ''], sources : [BillboardCollectionVS] }), BillboardCollectionFS, attributeIndices); this._compiledShaderRotation = this._shaderRotation; this._compiledShaderScaleByDistance = this._shaderScaleByDistance; + this._compiledShaderTranslucencyByDistance = this._shaderTranslucencyByDistance; } va = this._vaf.vaByPurpose[colorPassPurpose]; @@ -1207,13 +1258,15 @@ define([ if (!defined(this._spPick) || (this._shaderRotation && !this._compiledShaderRotationPick) || - (this._shaderScaleByDistance && !this._compiledShaderScaleByDistancePick)) { + (this._shaderScaleByDistance && !this._compiledShaderScaleByDistancePick) || + (this._shaderTranslucencyByDistance && !this._compiledShaderTranslucencyByDistancePick)) { this._spPick = context.getShaderCache().replaceShaderProgram( this._spPick, createShaderSource({ defines : ['RENDER_FOR_PICK', this._shaderRotation ? 'ROTATION' : '', - this._shaderScaleByDistance ? 'EYE_DISTANCE_SCALING' : ''], + this._shaderScaleByDistance ? 'EYE_DISTANCE_SCALING' : '', + this._shaderTranslucencyByDistance ? 'EYE_DISTANCE_TRANSLUCENCY' : ''], sources : [BillboardCollectionVS] }), createShaderSource({ @@ -1223,6 +1276,7 @@ define([ attributeIndices); this._compiledShaderRotationPick = this._shaderRotation; this._compiledShaderScaleByDistancePick = this._shaderScaleByDistance; + this._compiledShaderTranslucencyByDistancePick = this._shaderTranslucencyByDistance; } va = this._vaf.vaByPurpose[pickPassPurpose]; diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 53cd78896cf6..a28e7a0efbf9 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -6,6 +6,7 @@ define([ '../Core/Cartesian3', '../Core/Color', '../Core/defined', + '../Core/NearFarScalar', './Billboard', './LabelStyle', './HorizontalOrigin', @@ -17,6 +18,7 @@ define([ Cartesian3, Color, defined, + NearFarScalar, Billboard, LabelStyle, HorizontalOrigin, @@ -67,6 +69,7 @@ define([ this._eyeOffset = Cartesian3.clone(defaultValue(description.eyeOffset, Cartesian3.ZERO)); this._position = Cartesian3.clone(defaultValue(description.position, Cartesian3.ZERO)); this._scale = defaultValue(description.scale, 1.0); + this._translucencyByDistance = description.translucencyByDistance; this._labelCollection = labelCollection; this._glyphs = []; @@ -451,6 +454,53 @@ define([ } }; + /** + * Returns the near and far translucency properties of a Label based on the label's distance from the camera. + * + * @memberof Label + * + * @returns {NearFarScalar} The near/far translucency values based on camera distance to the billboard + * + * @see Label#setTranslucencyByDistance + */ + Label.prototype.getTranslucencyByDistance = function() { + return this._translucencyByDistance; + }; + + /** + * Sets near and far translucency properties of a Label based on the Label's distance from the camera. + * A label's translucency will interpolate between the {@link NearFarScalar#nearValue} and + * {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds + * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}. + * Outside of these ranges the label's translucency remains clamped to the nearest bound. If undefined, + * translucencyByDistance will be disabled. + * + * @memberof Label + * + * @param {NearFarScalar} translucency The configuration of near and far distances and their respective translucency values + * + * @exception {DeveloperError} far distance must be greater than near distance. + * + * @see Label#getTranslucencyByDistance + * + * @example + * // Example 1. + * // Set a label's translucencyByDistance to 1.0 when the + * // camera is 1500 meters from the label and disappear as + * // the camera distance approaches 8.0e6 meters. + * text.setTranslucencyByDistance(new NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0)); + * + * // Example 2. + * // disable translucency by distance + * text.setTranslucencyByDistance(undefined); + */ + Label.prototype.setTranslucencyByDistance = function(value) { + if (!NearFarScalar.equals(this._translucencyByDistance, value)) { + NearFarScalar.clone(value, this._translucencyByDistance); + rebindAllGlyphs(this); + } + }; + /** * Returns the 3D Cartesian offset applied to this label in eye coordinates. * @@ -726,7 +776,8 @@ define([ Color.equals(this._fillColor, other._fillColor) && Color.equals(this._outlineColor, other._outlineColor) && Cartesian2.equals(this._pixelOffset, other._pixelOffset) && - Cartesian3.equals(this._eyeOffset, other._eyeOffset); + Cartesian3.equals(this._eyeOffset, other._eyeOffset) && + NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance); }; /** diff --git a/Source/Scene/LabelCollection.js b/Source/Scene/LabelCollection.js index 977b5a7f6919..d971c7c1d5f8 100644 --- a/Source/Scene/LabelCollection.js +++ b/Source/Scene/LabelCollection.js @@ -177,6 +177,7 @@ define([ billboard.setHorizontalOrigin(HorizontalOrigin.LEFT); billboard.setVerticalOrigin(label._verticalOrigin); billboard.setScale(label._scale); + billboard.setTranslucencyByDistance(label._translucencyByDistance); billboard._pickIdThis = label; } diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index b5699cf95d54..a5e8cdb4d786 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -7,6 +7,7 @@ attribute vec2 pixelOffset; attribute vec4 eyeOffsetAndScale; // eye offset in meters attribute vec4 rotationAndAlignedAxis; attribute vec4 scaleByDistance; // near, nearScale, far, farScale +attribute vec4 translucencyByDistance; // near, nearTrans, far, farTrans #ifdef RENDER_FOR_PICK attribute vec4 pickColor; @@ -24,6 +25,23 @@ varying vec4 v_pickColor; varying vec4 v_color; #endif +float getNearFarScalar(vec4 nearFarScalar, float cameraDistSq) +{ + float valueAtMin = nearFarScalar.y; + float valueAtMax = nearFarScalar.w; + float nearDistanceSq = nearFarScalar.x * nearFarScalar.x; + float farDistanceSq = nearFarScalar.z * nearFarScalar.z; + + // ensure that t will fall within the range of [0.0, 1.0] + cameraDistSq = clamp(cameraDistSq, nearDistanceSq, farDistanceSq); + + float t = (cameraDistSq - nearDistanceSq) / (farDistanceSq - nearDistanceSq); + + t = pow(t, 0.15); + + return mix(valueAtMin, valueAtMax, t); +} + void main() { // Modifying this shader may also require modifications to Billboard.computeScreenSpacePosition @@ -44,8 +62,7 @@ void main() positionEC.xyz *= show; /////////////////////////////////////////////////////////////////////////// - -#ifdef EYE_DISTANCE_SCALING // scale based on eye distance + float lengthSq; if (czm_sceneMode == czm_sceneMode2D) { @@ -58,19 +75,13 @@ void main() lengthSq = dot(positionEC.xyz, positionEC.xyz); } - float scaleAtMin = scaleByDistance.y; - float scaleAtMax = scaleByDistance.w; - float nearDistanceSq = scaleByDistance.x * scaleByDistance.x; - float farDistanceSq = scaleByDistance.z * scaleByDistance.z; - - // ensure that t will fall within the range of [0.0, 1.0] - lengthSq = clamp(lengthSq, nearDistanceSq, farDistanceSq); - - float t = (lengthSq - nearDistanceSq) / (farDistanceSq - nearDistanceSq); - - t = pow(t, 0.15); +#ifdef EYE_DISTANCE_SCALING + scale *= getNearFarScalar(scaleByDistance, lengthSq); +#endif - scale *= mix(scaleAtMin, scaleAtMax, t); + float translucency = 1.0; +#ifdef EYE_DISTANCE_TRANSLUCENCY + translucency = getNearFarScalar(translucencyByDistance, lengthSq); #endif vec4 positionWC = czm_eyeToWindowCoordinates(positionEC); @@ -111,7 +122,9 @@ void main() #ifdef RENDER_FOR_PICK v_pickColor = pickColor; + v_pickColor.a *= translucency; #else v_color = color; + v_color.a *= translucency; #endif } From cdd9f47845d33a9d22c0f87cfbb4aa97bd8c7764 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 1 Oct 2013 09:51:26 -0400 Subject: [PATCH 02/10] Fixed typo in Billboard asset name. Signed-off-by: Alex Wood --- Apps/Sandcastle/gallery/Billboards.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/Billboards.html b/Apps/Sandcastle/gallery/Billboards.html index 53102c78e49b..39ddbc541d23 100644 --- a/Apps/Sandcastle/gallery/Billboards.html +++ b/Apps/Sandcastle/gallery/Billboards.html @@ -179,7 +179,7 @@ }); scene.getPrimitives().add(billboards); }; - image.src = '../images/Cesium_Logo_overlay.gif'; + image.src = '../images/Cesium_Logo_overlay.png'; } function addPointBillboards(scene, ellipsoid) { From c3f6e76e8d2d5d03383be6b9eeeba9e680a03353 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 1 Oct 2013 10:21:48 -0400 Subject: [PATCH 03/10] Fixed bug that would occur if some billboards in a collection did not use scale/translucencyByDistance, their default values would cause issues. For translucency and scale, we should default to 1.0 which results in an identity transformation (e.g., scale by 1). Signed-off-by: Alex Wood --- Apps/Sandcastle/gallery/Labels.html | 10 +++++++--- Source/Scene/Billboard.js | 2 +- Source/Scene/BillboardCollection.js | 12 ++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Apps/Sandcastle/gallery/Labels.html b/Apps/Sandcastle/gallery/Labels.html index ef2df1a47dc6..379c4da0fd3b 100644 --- a/Apps/Sandcastle/gallery/Labels.html +++ b/Apps/Sandcastle/gallery/Labels.html @@ -93,13 +93,17 @@ function labelTranslucencyByDistance(scene, ellipsoid) { Sandcastle.declare(labelTranslucencyByDistance); // For highlighting in Sandcastle. var labels = new Cesium.LabelCollection(); - var l = labels.add({ + labels.add({ + position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-73.94, 40.67)), + text : 'New York' + }); + labels.add({ position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.10, 39.57)), text : 'Philadelphia', - translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.0), - pixelOffset : new Cesium.Cartesian2(0, 50) + translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.0) }); + // add a billboard to mark Philadelphia on the globe var image = new Image(); image.onload = function() { var billboards = new Cesium.BillboardCollection(); diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 9ce41fde3e96..0ac869608efb 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -368,7 +368,7 @@ define([ * * @example * // Example 1. - * // Set a billboard's translucencyByDistance to 1.0 when the + * // Set a billboard's translucency to 1.0 when the * // camera is 1500 meters from the billboard and disappear as * // the camera distance approaches 8.0e6 meters. * b.setTranslucencyByDistance(new NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0)); diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index 09f8fd0782e0..ecb1b3d3a515 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -882,9 +882,9 @@ define([ var allPurposeWriters = vafWriters[allPassPurpose]; var writer = allPurposeWriters[attributeIndices.scaleByDistance]; var near = 0.0; - var nearValue = 0.0; - var far = 0.0; - var farValue = 0.0; + var nearValue = 1.0; + var far = 1.0; + var farValue = 1.0; var scale = billboard.getScaleByDistance(); if (defined(scale)) { @@ -911,9 +911,9 @@ define([ var allPurposeWriters = vafWriters[allPassPurpose]; var writer = allPurposeWriters[attributeIndices.translucencyByDistance]; var near = 0.0; - var nearValue = 0.0; - var far = 0.0; - var farValue = 0.0; + var nearValue = 1.0; + var far = 1.0; + var farValue = 1.0; var translucency = billboard.getTranslucencyByDistance(); if (defined(translucency)) { From aab439b75058040b3725dd46b1baddeaf6830e98 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 1 Oct 2013 12:08:12 -0400 Subject: [PATCH 04/10] Added unit tests for Billboard.translucencyByDistance and Label.translucencyByDistance. Cleanup and fixes related to unit tests. Signed-off-by: Alex Wood --- Source/Scene/Label.js | 19 +++++-- Specs/Scene/BillboardCollectionSpec.js | 73 +++++++++++++++++++++++++- Specs/Scene/LabelCollectionSpec.js | 72 ++++++++++++++++++++++++- 3 files changed, 159 insertions(+), 5 deletions(-) diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index a28e7a0efbf9..30fa4b530671 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -48,6 +48,8 @@ define([ * @alias Label * @internalConstructor * + * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near + * * @see LabelCollection * @see LabelCollection#add * @@ -56,6 +58,11 @@ define([ var Label = function(description, labelCollection) { description = defaultValue(description, defaultValue.EMPTY_OBJECT); + if (defined(description.translucencyByDistance) && + description.translucencyByDistance.far <= description.translucencyByDistance.near) { + throw new DeveloperError('translucencyByDistance.far must be greater than translucencyByDistance.near.'); + } + this._text = defaultValue(description.text, ''); this._show = defaultValue(description.show, true); this._font = defaultValue(description.font, '30px sans-serif'); @@ -495,10 +502,16 @@ define([ * text.setTranslucencyByDistance(undefined); */ Label.prototype.setTranslucencyByDistance = function(value) { - if (!NearFarScalar.equals(this._translucencyByDistance, value)) { - NearFarScalar.clone(value, this._translucencyByDistance); - rebindAllGlyphs(this); + if (NearFarScalar.equals(this._translucencyByDistance, value)) { + return; } + + if (value.far <= value.near) { + throw new DeveloperError('far distance must be greater than near distance.'); + } + + this._translucencyByDistance = NearFarScalar.clone(value, this._translucencyByDistance); + rebindAllGlyphs(this); }; /** diff --git a/Specs/Scene/BillboardCollectionSpec.js b/Specs/Scene/BillboardCollectionSpec.js index 4d944a961713..fb5df209f561 100644 --- a/Specs/Scene/BillboardCollectionSpec.js +++ b/Specs/Scene/BillboardCollectionSpec.js @@ -124,6 +124,7 @@ defineSuite([ expect(b.getRotation()).toEqual(0.0); expect(b.getAlignedAxis()).toEqual(Cartesian3.ZERO); expect(b.getScaleByDistance()).not.toBeDefined(); + expect(b.getTranslucencyByDistance()).not.toBeDefined(); expect(b.getWidth()).not.toBeDefined(); expect(b.getHeight()).not.toBeDefined(); }); @@ -147,6 +148,7 @@ defineSuite([ rotation : 1.0, alignedAxis : new Cartesian3(1.0, 2.0, 3.0), scaleByDistance : new NearFarScalar(1.0, 3.0, 1.0e6, 0.0), + translucencyByDistance : new NearFarScalar(1.0, 1.0, 1.0e6, 0.0), width : 300.0, height : 200.0 }); @@ -166,6 +168,7 @@ defineSuite([ expect(b.getRotation()).toEqual(1.0); expect(b.getAlignedAxis()).toEqual(new Cartesian3(1.0, 2.0, 3.0)); expect(b.getScaleByDistance()).toEqual(new NearFarScalar(1.0, 3.0, 1.0e6, 0.0)); + expect(b.getTranslucencyByDistance()).toEqual(new NearFarScalar(1.0, 1.0, 1.0e6, 0.0)); expect(b.getWidth()).toEqual(300.0); expect(b.getHeight()).toEqual(200.0); }); @@ -191,6 +194,7 @@ defineSuite([ b.setWidth(300.0); b.setHeight(200.0); b.setScaleByDistance(new NearFarScalar(1.0e6, 3.0, 1.0e8, 0.0)); + b.setTranslucencyByDistance(new NearFarScalar(1.0e6, 1.0, 1.0e8, 0.0)); expect(b.getShow()).toEqual(false); expect(b.getPosition()).toEqual(new Cartesian3(1.0, 2.0, 3.0)); @@ -207,6 +211,7 @@ defineSuite([ expect(b.getRotation()).toEqual(1.0); expect(b.getAlignedAxis()).toEqual(new Cartesian3(1.0, 2.0, 3.0)); expect(b.getScaleByDistance()).toEqual(new NearFarScalar(1.0e6, 3.0, 1.0e8, 0.0)); + expect(b.getTranslucencyByDistance()).toEqual(new NearFarScalar(1.0e6, 1.0, 1.0e8, 0.0)); expect(b.getWidth()).toEqual(300.0); expect(b.getHeight()).toEqual(200.0); }); @@ -217,7 +222,13 @@ defineSuite([ expect(b.getScaleByDistance()).not.toBeDefined(); }); - it('set billboard scaleByDistance farValue to 0', function() { + it('disable billboard setTranslucencyByDistance', function() { + var b = billboards.add(); + b.setTranslucencyByDistance(undefined); + expect(b.getTranslucencyByDistance()).not.toBeDefined(); + }); + + it('render billboard with scaleByDistance', function() { billboards.setTextureAtlas(createTextureAtlas([greenImage])); billboards.add({ position : { @@ -252,6 +263,41 @@ defineSuite([ us.update(context, createFrameState(createCamera(context))); }); + it('render billboard with translucencyByDistance', function() { + billboards.setTextureAtlas(createTextureAtlas([greenImage])); + billboards.add({ + position : { + x : 0.0, + y : 0.0, + z : 0.0 + }, + translucencyByDistance: new NearFarScalar(1.0, 1.0, 3.0, 0.0), + imageIndex : 0 + }); + + // verify basis + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + // camera at 1.0 above billboard, expect green pixel to be rendered, as translucency is near 1.0 + var us = context.getUniformState(); + var eye = new Cartesian3(0.0, 0.0, 1.0); + var target = Cartesian3.ZERO; + var up = Cartesian3.UNIT_Y; + us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); + render(context, frameState, billboards); + expect(context.readPixels()).toEqual([0, 255, 0, 255]); + // clear screen + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + // camera at 6.0 above billboard, expect no green pixels to be rendered, as translucency is 0.0 + eye = new Cartesian3(0.0, 0.0, 6.0); + us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); + render(context, frameState, billboards); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + // revert framestate + us.update(context, createFrameState(createCamera(context))); + }); + it('throws setScaleByDistance with nearDistance === farDistance', function() { var b = billboards.add(); var scale = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); @@ -277,6 +323,31 @@ defineSuite([ }).toThrow(); }); + it('throws setTranslucencyByDistance with nearDistance === farDistance', function() { + var b = billboards.add(); + var translucency = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); + expect(function() { + b.setTranslucencyByDistance(translucency); + }).toThrow(); + }); + + it('throws new billboard with invalid translucencyByDistance (nearDistance === farDistance)', function() { + var translucency = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); + expect(function() { + billboards.add({ + translucencyByDistance : translucency + }); + }).toThrow(); + }); + + it('throws setTranslucencyByDistance with nearDistance > farDistance', function() { + var b = billboards.add(); + var translucency = new NearFarScalar(1.0e9, 1.0, 1.0e5, 1.0); + expect(function() { + b.setTranslucencyByDistance(translucency); + }).toThrow(); + }); + it('throws with non number Index', function() { var b = billboards.add(); expect(function() { diff --git a/Specs/Scene/LabelCollectionSpec.js b/Specs/Scene/LabelCollectionSpec.js index 490b9240da57..30ebd838a017 100644 --- a/Specs/Scene/LabelCollectionSpec.js +++ b/Specs/Scene/LabelCollectionSpec.js @@ -14,6 +14,7 @@ defineSuite([ 'Core/Cartographic', 'Core/Color', 'Core/Math', + 'Core/NearFarScalar', 'Renderer/ClearCommand', 'Scene/HorizontalOrigin', 'Scene/VerticalOrigin', @@ -35,6 +36,7 @@ defineSuite([ Cartographic, Color, CesiumMath, + NearFarScalar, ClearCommand, HorizontalOrigin, VerticalOrigin, @@ -83,6 +85,7 @@ defineSuite([ expect(label.getHorizontalOrigin()).toEqual(HorizontalOrigin.LEFT); expect(label.getVerticalOrigin()).toEqual(VerticalOrigin.BOTTOM); expect(label.getScale()).toEqual(1.0); + expect(label.getTranslucencyByDistance()).not.toBeDefined(); }); it('can add a label with specified values', function() { @@ -110,6 +113,7 @@ defineSuite([ var horizontalOrigin = HorizontalOrigin.LEFT; var verticalOrigin = VerticalOrigin.BOTTOM; var scale = 2.0; + var translucency = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); var label = labels.add({ show : show, position : position, @@ -123,7 +127,8 @@ defineSuite([ eyeOffset : eyeOffset, horizontalOrigin : horizontalOrigin, verticalOrigin : verticalOrigin, - scale : scale + scale : scale, + translucencyByDistance : translucency }); expect(label.getShow()).toEqual(show); @@ -139,6 +144,7 @@ defineSuite([ expect(label.getHorizontalOrigin()).toEqual(horizontalOrigin); expect(label.getVerticalOrigin()).toEqual(verticalOrigin); expect(label.getScale()).toEqual(scale); + expect(label.getTranslucencyByDistance()).toEqual(translucency); }); it('can specify font using units other than pixels', function() { @@ -635,6 +641,42 @@ defineSuite([ expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); }); + it('render label with translucencyByDistance', function() { + labels.add({ + position : { + x : 0.0, + y : 0.0, + z : 0.0 + }, + text : 'x', + horizontalOrigin : HorizontalOrigin.CENTER, + verticalOrigin : VerticalOrigin.CENTER, + translucencyByDistance: new NearFarScalar(1.0, 1.0, 3.0, 0.0) + }); + + // verify basis + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + // camera at 1.0 above label, expect label to be rendered, as translucency is near 1.0 + var us = context.getUniformState(); + var eye = new Cartesian3(0.0, 0.0, 1.0); + var target = Cartesian3.ZERO; + var up = Cartesian3.UNIT_Y; + us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); + render(context, frameState, labels); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + // clear screen + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + // camera at 6.0 above label, expect no pixels to be rendered, as translucency is 0.0 + eye = new Cartesian3(0.0, 0.0, 6.0); + us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); + render(context, frameState, labels); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + // revert framestate + us.update(context, createFrameState(createCamera(context))); + }); + it('can pick a label', function() { var label = labels.add({ position : { @@ -793,6 +835,7 @@ defineSuite([ var horizontalOrigin = HorizontalOrigin.LEFT; var verticalOrigin = VerticalOrigin.BOTTOM; var scale = 2.0; + var translucency = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); label.setShow(show); label.setPosition(position); @@ -807,6 +850,7 @@ defineSuite([ label.setHorizontalOrigin(horizontalOrigin); label.setVerticalOrigin(verticalOrigin); label.setScale(scale); + label.setTranslucencyByDistance(translucency); expect(label.getShow()).toEqual(show); expect(label.getPosition()).toEqual(position); @@ -821,6 +865,7 @@ defineSuite([ expect(label.getHorizontalOrigin()).toEqual(horizontalOrigin); expect(label.getVerticalOrigin()).toEqual(verticalOrigin); expect(label.getScale()).toEqual(scale); + expect(label.getTranslucencyByDistance()).toEqual(translucency); }); it('is destroyed after being removed', function() { @@ -1508,6 +1553,31 @@ defineSuite([ }).toThrow(); }); + it('Label.setTranslucencyByDistance throws with nearDistance === farDistance', function() { + var label = labels.add(); + var translucency = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); + expect(function() { + label.setTranslucencyByDistance(translucency); + }).toThrow(); + }); + + it('new label throws with invalid translucencyByDistance (nearDistance === farDistance)', function() { + var translucency = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); + expect(function() { + labels.add({ + translucencyByDistance : translucency + }); + }).toThrow(); + }); + + it('Label.setTranslucencyByDistance throws with nearDistance > farDistance', function() { + var label = labels.add(); + var translucency = new NearFarScalar(1.0e9, 1.0, 1.0e5, 1.0); + expect(function() { + label.setTranslucencyByDistance(translucency); + }).toThrow(); + }); + it('destroys texture atlas when destroying', function() { labels.add({ text : 'a' From c3fade1851f55c373217681773a7b7416e4e4161 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 1 Oct 2013 14:16:26 -0400 Subject: [PATCH 05/10] Added unit tests for picking labels and billboards that use translucencyByDistance. Picking fixes for translucencyByDistance. Updated Changes.MD. Signed-off-by: Alex Wood --- CHANGES.md | 5 +++++ Source/Scene/LabelCollection.js | 2 +- Source/Shaders/BillboardCollectionFS.glsl | 6 ++++++ Source/Shaders/BillboardCollectionVS.glsl | 3 ++- Specs/Scene/BillboardCollectionSpec.js | 22 ++++++++++++++++++++++ Specs/Scene/LabelCollectionSpec.js | 23 +++++++++++++++++++++++ 6 files changed, 59 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c5fa76d14c09..2733ca95cac5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,11 @@ Change Log Beta Releases ------------- +### b22 - 2013-11-01 + +* Added `Billboard.translucencyByDistance` and `Label.translucencyByDistance` to control minimum/maximum translucency based on camera distance. + + ### b21 - 2013-10-01 * Breaking changes: diff --git a/Source/Scene/LabelCollection.js b/Source/Scene/LabelCollection.js index d971c7c1d5f8..65a6529b8c00 100644 --- a/Source/Scene/LabelCollection.js +++ b/Source/Scene/LabelCollection.js @@ -177,11 +177,11 @@ define([ billboard.setHorizontalOrigin(HorizontalOrigin.LEFT); billboard.setVerticalOrigin(label._verticalOrigin); billboard.setScale(label._scale); - billboard.setTranslucencyByDistance(label._translucencyByDistance); billboard._pickIdThis = label; } glyph.billboard.setImageIndex(glyphTextureInfo.index); + glyph.billboard.setTranslucencyByDistance(label._translucencyByDistance); } } diff --git a/Source/Shaders/BillboardCollectionFS.glsl b/Source/Shaders/BillboardCollectionFS.glsl index 46e9ad146425..4e8d5546d8c4 100644 --- a/Source/Shaders/BillboardCollectionFS.glsl +++ b/Source/Shaders/BillboardCollectionFS.glsl @@ -4,6 +4,7 @@ varying vec2 v_textureCoordinates; #ifdef RENDER_FOR_PICK varying vec4 v_pickColor; +varying float v_pickTranslucency; #else varying vec4 v_color; #endif @@ -11,6 +12,11 @@ varying vec4 v_color; void main() { #ifdef RENDER_FOR_PICK + if (v_pickTranslucency == 0.0) + { + discard; + } + vec4 vertexColor = vec4(1.0, 1.0, 1.0, 1.0); #else vec4 vertexColor = v_color; diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index a5e8cdb4d786..119fa313d8b0 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -21,6 +21,7 @@ varying vec2 v_textureCoordinates; #ifdef RENDER_FOR_PICK varying vec4 v_pickColor; +varying float v_pickTranslucency; #else varying vec4 v_color; #endif @@ -122,7 +123,7 @@ void main() #ifdef RENDER_FOR_PICK v_pickColor = pickColor; - v_pickColor.a *= translucency; + v_pickTranslucency = translucency; #else v_color = color; v_color.a *= translucency; diff --git a/Specs/Scene/BillboardCollectionSpec.js b/Specs/Scene/BillboardCollectionSpec.js index fb5df209f561..fb656e048479 100644 --- a/Specs/Scene/BillboardCollectionSpec.js +++ b/Specs/Scene/BillboardCollectionSpec.js @@ -1186,6 +1186,28 @@ defineSuite([ expect(pickedObject).not.toBeDefined(); }); + it('pick a billboard using translucencyByDistance', function() { + billboards.setTextureAtlas(createTextureAtlas([whiteImage])); + var b = billboards.add({ + position : { + x : 0.0, + y : 0.0, + z : 0.0 + }, + imageIndex : 0 + }); + + var translucency = new NearFarScalar(1.0, 1.0, 3.0e9, 0.9); + b.setTranslucencyByDistance(translucency); + var pickedObject = pick(context, frameState, billboards, 0, 0); + expect(pickedObject.primitive).toEqual(b); + translucency.nearValue = 0.0; + translucency.farValue = 0.0; + b.setTranslucencyByDistance(translucency); + pickedObject = pick(context, frameState, billboards, 0, 0); + expect(pickedObject).toBeUndefined(); + }); + it('computes screen space position (1)', function() { billboards.setTextureAtlas(createTextureAtlas([whiteImage])); var b = billboards.add({ diff --git a/Specs/Scene/LabelCollectionSpec.js b/Specs/Scene/LabelCollectionSpec.js index 30ebd838a017..a1882b7e5665 100644 --- a/Specs/Scene/LabelCollectionSpec.js +++ b/Specs/Scene/LabelCollectionSpec.js @@ -710,6 +710,29 @@ defineSuite([ expect(pickedObject).toBeUndefined(); }); + it('pick a label using translucencyByDistance', function() { + var label = labels.add({ + position : { + x : 0.0, + y : 0.0, + z : 0.0 + }, + text : 'x', + horizontalOrigin : HorizontalOrigin.CENTER, + verticalOrigin : VerticalOrigin.CENTER + }); + + var translucency = new NearFarScalar(1.0, 1.0, 3.0e9, 0.9); + label.setTranslucencyByDistance(translucency); + var pickedObject = pick(context, frameState, labels, 0, 0); + expect(pickedObject.primitive).toEqual(label); + translucency.nearValue = 0.0; + translucency.farValue = 0.0; + label.setTranslucencyByDistance(translucency); + pickedObject = pick(context, frameState, labels, 0, 0); + expect(pickedObject).toBeUndefined(); + }); + it('throws when calling get without an index', function() { expect(function() { labels.get(); From c56c113fb561f5e28b6adb28169a85de98054d5f Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 1 Oct 2013 14:37:48 -0400 Subject: [PATCH 06/10] Minor documentation fixes. Signed-off-by: Alex Wood --- Source/Scene/BillboardCollection.js | 2 -- Source/Scene/LabelCollection.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index ecb1b3d3a515..4441fe2da831 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -262,8 +262,6 @@ define([ * horizontalOrigin : HorizontalOrigin.CENTER, * verticalOrigin : VerticalOrigin.CENTER, * scale : 1.0, - * scaleByDistance : new NearFarScalar(5e6, 1.0, 2e7, 0.0), - * translucencyByDistance : new NearFarScalar(5e6, 1.0, 2e7, 0.0), * imageIndex : 0, * color : Color.WHITE * }); diff --git a/Source/Scene/LabelCollection.js b/Source/Scene/LabelCollection.js index 65a6529b8c00..d504097f9b9d 100644 --- a/Source/Scene/LabelCollection.js +++ b/Source/Scene/LabelCollection.js @@ -376,7 +376,7 @@ define([ * eyeOffset : Cartesian3.ZERO, * horizontalOrigin : HorizontalOrigin.LEFT, * verticalOrigin : VerticalOrigin.BOTTOM, - * scale : 1.0, + * scale : 1.0 * }); * * // Example 2: Specify only the label's cartographic position, From 0d54784dd8e753cfe7a90c92a890a0b20fb692f3 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 2 Oct 2013 14:04:20 -0400 Subject: [PATCH 07/10] Add translucencyByDistance support to DynamicScene. --- CHANGES.md | 4 +++- Source/DynamicScene/DynamicBillboard.js | 19 +++++++++++---- .../DynamicBillboardVisualizer.js | 7 +++++- Source/DynamicScene/DynamicLabel.js | 13 +++++++++- Source/DynamicScene/DynamicLabelVisualizer.js | 5 ++++ Specs/DynamicScene/DynamicBillboardSpec.js | 24 ++++++++++++------- .../DynamicBillboardVisualizerSpec.js | 12 ++++++---- Specs/DynamicScene/DynamicLabelSpec.js | 10 ++++++++ .../DynamicLabelVisualizerSpec.js | 6 +++++ 9 files changed, 81 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2733ca95cac5..685a8dc5a019 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,7 +6,9 @@ Beta Releases ### b22 - 2013-11-01 -* Added `Billboard.translucencyByDistance` and `Label.translucencyByDistance` to control minimum/maximum translucency based on camera distance. +* Breaking changes: + * Renamed `DynamicBillboard.nearFarScalar` to `DynamicBillboard.scaleByDistance`. +* Added `Billboard.setTranslucencyByDistance`, `Label.setTranslucencyByDistance`, `DynamicBillboard.translucencyByDistance`, and `DynamicLabel.translucencyByDistance` to control minimum/maximum translucency based on camera distance. ### b21 - 2013-10-01 diff --git a/Source/DynamicScene/DynamicBillboard.js b/Source/DynamicScene/DynamicBillboard.js index e8465da28021..c8a48fdb3ef2 100644 --- a/Source/DynamicScene/DynamicBillboard.js +++ b/Source/DynamicScene/DynamicBillboard.js @@ -33,7 +33,8 @@ define(['../Core/defaultValue', this._eyeOffset = undefined; this._pixelOffset = undefined; this._show = undefined; - this._nearFarScalar = undefined; + this._scaleByDistance = undefined; + this._translucencyByDistance = undefined; this._propertyChanged = new Event(); }; @@ -141,7 +142,15 @@ define(['../Core/defaultValue', * @memberof DynamicBillboard.prototype * @type {Property} */ - nearFarScalar : createDynamicPropertyDescriptor('nearFarScalar', '_nearFarScalar') + scaleByDistance : createDynamicPropertyDescriptor('scaleByDistance', '_scaleByDistance'), + + /** + * Gets or sets the {@link NearFarScalar} {@link Property} used to set translucency based on distance. + * If undefined, a constant size is used. + * @memberof DynamicBillboard.prototype + * @type {Property} + */ + translucencyByDistance : createDynamicPropertyDescriptor('translucencyByDistance', '_translucencyByDistance') }); /** @@ -167,7 +176,8 @@ define(['../Core/defaultValue', result.verticalOrigin = this._verticalOrigin; result.width = this._width; result.height = this._height; - result.nearFarScalar = this._nearFarScalar; + result.scaleByDistance = this._scaleByDistance; + result.translucencyByDistance = this._translucencyByDistance; return result; }; @@ -195,7 +205,8 @@ define(['../Core/defaultValue', this.verticalOrigin = defaultValue(this._verticalOrigin, source._verticalOrigin); this.width = defaultValue(this._width, source._width); this.height = defaultValue(this._height, source._height); - this.nearFarScalar = defaultValue(this._nearFarScalar, source._nearFarScalar); + this.scaleByDistance = defaultValue(this._scaleByDistance, source._scaleByDistance); + this.translucencyByDistance = defaultValue(this._translucencyByDistance, source._translucencyByDistance); }; return DynamicBillboard; diff --git a/Source/DynamicScene/DynamicBillboardVisualizer.js b/Source/DynamicScene/DynamicBillboardVisualizer.js index 7d9dccbf6988..60ac058cc921 100644 --- a/Source/DynamicScene/DynamicBillboardVisualizer.js +++ b/Source/DynamicScene/DynamicBillboardVisualizer.js @@ -352,10 +352,15 @@ define([ billboard.setHeight(property.getValue(time)); } - property = dynamicBillboard._nearFarScalar; + property = dynamicBillboard._scaleByDistance; if (defined(property)) { billboard.setScaleByDistance(property.getValue(time)); } + + property = dynamicBillboard._translucencyByDistance; + if (defined(property)) { + billboard.setTranslucencyByDistance(property.getValue(time)); + } } DynamicBillboardVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, added, dynamicObjects) { diff --git a/Source/DynamicScene/DynamicLabel.js b/Source/DynamicScene/DynamicLabel.js index 5d1d0d2a6cd8..d479d0576d17 100644 --- a/Source/DynamicScene/DynamicLabel.js +++ b/Source/DynamicScene/DynamicLabel.js @@ -32,6 +32,7 @@ define(['../Core/defaultValue', this._pixelOffset = undefined; this._scale = undefined; this._show = undefined; + this._translucencyByDistance = undefined; this._propertyChanged = new Event(); }; @@ -129,7 +130,15 @@ define(['../Core/defaultValue', * @memberof DynamicLabel.prototype * @type {Property} */ - show : createDynamicPropertyDescriptor('show', '_show') + show : createDynamicPropertyDescriptor('show', '_show'), + + /** + * Gets or sets the {@link NearFarScalar} {@link Property} used to set translucency based on distance. + * If undefined, a constant size is used. + * @memberof DynamicLabel.prototype + * @type {Property} + */ + translucencyByDistance : createDynamicPropertyDescriptor('translucencyByDistance', '_translucencyByDistance') }); /** @@ -155,6 +164,7 @@ define(['../Core/defaultValue', result.verticalOrigin = this.verticalOrigin; result.eyeOffset = this.eyeOffset; result.pixelOffset = this.pixelOffset; + result.translucencyByDistance = this._translucencyByDistance; return result; }; @@ -182,6 +192,7 @@ define(['../Core/defaultValue', this.verticalOrigin = defaultValue(this.verticalOrigin, source.verticalOrigin); this.eyeOffset = defaultValue(this.eyeOffset, source.eyeOffset); this.pixelOffset = defaultValue(this.pixelOffset, source.pixelOffset); + this.translucencyByDistance = defaultValue(this._translucencyByDistance, source._translucencyByDistance); }; return DynamicLabel; diff --git a/Source/DynamicScene/DynamicLabelVisualizer.js b/Source/DynamicScene/DynamicLabelVisualizer.js index 63c87b618f39..070365e50b32 100644 --- a/Source/DynamicScene/DynamicLabelVisualizer.js +++ b/Source/DynamicScene/DynamicLabelVisualizer.js @@ -331,6 +331,11 @@ define([ label.setVerticalOrigin(verticalOrigin); } } + + property = dynamicLabel._translucencyByDistance; + if (defined(property)) { + label.setTranslucencyByDistance(property.getValue(time)); + } } DynamicLabelVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, added, dynamicObjects) { diff --git a/Specs/DynamicScene/DynamicBillboardSpec.js b/Specs/DynamicScene/DynamicBillboardSpec.js index 4da47686e7e8..cb916c5a507f 100644 --- a/Specs/DynamicScene/DynamicBillboardSpec.js +++ b/Specs/DynamicScene/DynamicBillboardSpec.js @@ -34,7 +34,8 @@ defineSuite([ source.show = new ConstantProperty(false); source.width = new ConstantProperty(24); source.height = new ConstantProperty(36); - source.nearFarScalar = new ConstantProperty(new NearFarScalar()); + source.scaleByDistance = new ConstantProperty(new NearFarScalar()); + source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); var target = new DynamicBillboard(); target.merge(source); @@ -51,7 +52,8 @@ defineSuite([ expect(target.show).toBe(source.show); expect(target.width).toBe(source.width); expect(target.height).toBe(source.height); - expect(target.nearFarScalar).toBe(source.nearFarScalar); + expect(target.scaleByDistance).toBe(source.scaleByDistance); + expect(target.translucencyByDistance).toBe(source.translucencyByDistance); }); it('merge does not assign assigned properties', function() { @@ -68,7 +70,8 @@ defineSuite([ source.show = new ConstantProperty(false); source.width = new ConstantProperty(24); source.height = new ConstantProperty(36); - source.nearFarScalar = new ConstantProperty(new NearFarScalar()); + source.scaleByDistance = new ConstantProperty(new NearFarScalar()); + source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); var image = new ConstantProperty(''); var rotation = new ConstantProperty(5); @@ -82,7 +85,8 @@ defineSuite([ var show = new ConstantProperty(false); var width = new ConstantProperty(2); var height = new ConstantProperty(3); - var nearFarScalar = new ConstantProperty(new NearFarScalar()); + var scaleByDistance = new ConstantProperty(new NearFarScalar()); + var translucencyByDistance = new ConstantProperty(new NearFarScalar()); var target = new DynamicBillboard(); target.image = image; @@ -97,7 +101,8 @@ defineSuite([ target.show = show; target.width = width; target.height = height; - target.nearFarScalar = nearFarScalar; + target.scaleByDistance = scaleByDistance; + target.translucencyByDistance = translucencyByDistance; target.merge(source); @@ -113,7 +118,8 @@ defineSuite([ expect(target.show).toBe(show); expect(target.width).toBe(width); expect(target.height).toBe(height); - expect(target.nearFarScalar).toBe(nearFarScalar); + expect(target.scaleByDistance).toBe(scaleByDistance); + expect(target.translucencyByDistance).toBe(translucencyByDistance); }); it('clone works', function() { @@ -130,7 +136,8 @@ defineSuite([ source.show = new ConstantProperty(false); source.width = new ConstantProperty(24); source.height = new ConstantProperty(36); - source.nearFarScalar = new ConstantProperty(new NearFarScalar()); + source.scaleByDistance = new ConstantProperty(new NearFarScalar()); + source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); var result = source.clone(); expect(result.image).toBe(source.image); @@ -145,7 +152,8 @@ defineSuite([ expect(result.show).toBe(source.show); expect(result.width).toBe(source.width); expect(result.height).toBe(source.height); - expect(result.nearFarScalar).toBe(source.nearFarScalar); + expect(result.scaleByDistance).toBe(source.scaleByDistance); + expect(result.translucencyByDistance).toBe(source.translucencyByDistance); }); it('merge throws if source undefined', function() { diff --git a/Specs/DynamicScene/DynamicBillboardVisualizerSpec.js b/Specs/DynamicScene/DynamicBillboardVisualizerSpec.js index ae493558e6b6..dcc8ebc90f20 100644 --- a/Specs/DynamicScene/DynamicBillboardVisualizerSpec.js +++ b/Specs/DynamicScene/DynamicBillboardVisualizerSpec.js @@ -153,7 +153,8 @@ defineSuite([ billboard.pixelOffset = new ConstantProperty(new Cartesian2(3, 2)); billboard.width = new ConstantProperty(15); billboard.height = new ConstantProperty(5); - billboard.nearFarScalar = new ConstantProperty(new NearFarScalar()); + billboard.scaleByDistance = new ConstantProperty(new NearFarScalar()); + billboard.translucencyByDistance = new ConstantProperty(new NearFarScalar()); visualizer.update(time); @@ -174,7 +175,8 @@ defineSuite([ expect(bb.getVerticalOrigin()).toEqual(testObject.billboard.verticalOrigin.getValue(time)); expect(bb.getWidth()).toEqual(testObject.billboard.width.getValue(time)); expect(bb.getHeight()).toEqual(testObject.billboard.height.getValue(time)); - expect(bb.getScaleByDistance()).toEqual(testObject.billboard.nearFarScalar.getValue(time)); + expect(bb.getScaleByDistance()).toEqual(testObject.billboard.scaleByDistance.getValue(time)); + expect(bb.getTranslucencyByDistance()).toEqual(testObject.billboard.translucencyByDistance.getValue(time)); } return bb.getShow(); //true once the image is loaded. }); @@ -194,7 +196,8 @@ defineSuite([ billboard.pixelOffset = new ConstantProperty(new Cartesian2(2, 3)); billboard.width = new ConstantProperty(17); billboard.height = new ConstantProperty(12); - billboard.nearFarScalar = new ConstantProperty(new NearFarScalar()); + billboard.scaleByDistance = new ConstantProperty(new NearFarScalar()); + billboard.translucencyByDistance = new ConstantProperty(new NearFarScalar()); waitsFor(function() { visualizer.update(time); @@ -211,7 +214,8 @@ defineSuite([ expect(bb.getPixelOffset()).toEqual(testObject.billboard.pixelOffset.getValue(time)); expect(bb.getWidth()).toEqual(testObject.billboard.width.getValue(time)); expect(bb.getHeight()).toEqual(testObject.billboard.height.getValue(time)); - expect(bb.getScaleByDistance()).toEqual(testObject.billboard.nearFarScalar.getValue(time)); + expect(bb.getScaleByDistance()).toEqual(testObject.billboard.scaleByDistance.getValue(time)); + expect(bb.getTranslucencyByDistance()).toEqual(testObject.billboard.translucencyByDistance.getValue(time)); } return imageReady; }); diff --git a/Specs/DynamicScene/DynamicLabelSpec.js b/Specs/DynamicScene/DynamicLabelSpec.js index e8d499c7ef1f..d148583e4461 100644 --- a/Specs/DynamicScene/DynamicLabelSpec.js +++ b/Specs/DynamicScene/DynamicLabelSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', + 'Core/NearFarScalar', 'Scene/HorizontalOrigin', 'Scene/VerticalOrigin', 'Scene/LabelStyle', @@ -13,6 +14,7 @@ defineSuite([ Cartesian2, Cartesian3, Color, + NearFarScalar, HorizontalOrigin, VerticalOrigin, LabelStyle, @@ -34,6 +36,7 @@ defineSuite([ source.pixelOffset = new ConstantProperty(Cartesian2.UNIT_X); source.scale = new ConstantProperty(1); source.show = new ConstantProperty(false); + source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); var target = new DynamicLabel(); target.merge(source); @@ -50,6 +53,7 @@ defineSuite([ expect(target.pixelOffset).toBe(source.pixelOffset); expect(target.scale).toBe(source.scale); expect(target.show).toBe(source.show); + expect(target.translucencyByDistance).toBe(source.translucencyByDistance); }); it('merge does not assign assigned properties', function() { @@ -66,6 +70,7 @@ defineSuite([ source.pixelOffset = new ConstantProperty(Cartesian2.UNIT_X); source.scale = new ConstantProperty(1); source.show = new ConstantProperty(false); + source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); var text = new ConstantProperty('my text'); var font = new ConstantProperty('10px serif'); @@ -79,6 +84,7 @@ defineSuite([ var pixelOffset = new ConstantProperty(Cartesian2.UNIT_Y); var scale = new ConstantProperty(2); var show = new ConstantProperty(true); + var translucencyByDistance = new ConstantProperty(new NearFarScalar()); var target = new DynamicLabel(); target.text = text; @@ -93,6 +99,7 @@ defineSuite([ target.pixelOffset = pixelOffset; target.scale = scale; target.show = show; + target.translucencyByDistance = translucencyByDistance; target.merge(source); @@ -108,6 +115,7 @@ defineSuite([ expect(target.pixelOffset).toBe(pixelOffset); expect(target.scale).toBe(scale); expect(target.show).toBe(show); + expect(target.translucencyByDistance).toBe(translucencyByDistance); }); it('clone works', function() { @@ -124,6 +132,7 @@ defineSuite([ source.pixelOffset = new ConstantProperty(Cartesian2.UNIT_X); source.scale = new ConstantProperty(1); source.show = new ConstantProperty(false); + source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); var result = source.clone(); expect(result.text).toBe(source.text); @@ -138,6 +147,7 @@ defineSuite([ expect(result.pixelOffset).toBe(source.pixelOffset); expect(result.scale).toBe(source.scale); expect(result.show).toBe(source.show); + expect(result.translucencyByDistance).toBe(source.translucencyByDistance); }); it('merge throws if source undefined', function() { diff --git a/Specs/DynamicScene/DynamicLabelVisualizerSpec.js b/Specs/DynamicScene/DynamicLabelVisualizerSpec.js index 5cbb1e1afbb8..13e4dd844f19 100644 --- a/Specs/DynamicScene/DynamicLabelVisualizerSpec.js +++ b/Specs/DynamicScene/DynamicLabelVisualizerSpec.js @@ -10,6 +10,7 @@ defineSuite([ 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', + 'Core/NearFarScalar', 'Scene/LabelCollection', 'Scene/HorizontalOrigin', 'Scene/VerticalOrigin', @@ -25,6 +26,7 @@ defineSuite([ Cartesian2, Cartesian3, Color, + NearFarScalar, LabelCollection, HorizontalOrigin, VerticalOrigin, @@ -148,6 +150,7 @@ defineSuite([ label.pixelOffset = new ConstantProperty(new Cartesian2(3, 2)); label.scale = new ConstantProperty(12.5); label.show = new ConstantProperty(true); + label.translucencyByDistance = new ConstantProperty(new NearFarScalar()); visualizer.update(time); @@ -169,6 +172,7 @@ defineSuite([ expect(l.getPixelOffset()).toEqual(testObject.label.pixelOffset.getValue(time)); expect(l.getScale()).toEqual(testObject.label.scale.getValue(time)); expect(l.getShow()).toEqual(testObject.label.show.getValue(time)); + expect(l.getTranslucencyByDistance()).toEqual(testObject.label.translucencyByDistance.getValue(time)); testObject.position = new ConstantProperty(new Cartesian3(5678, 1234, 1293434)); label.text = new ConstantProperty('b'); @@ -183,6 +187,7 @@ defineSuite([ label.pixelOffset = new ConstantProperty(new Cartesian2(2, 3)); label.scale = new ConstantProperty(2.5); label.show = new ConstantProperty(true); + label.translucencyByDistance = new ConstantProperty(new NearFarScalar()); visualizer.update(time); expect(l.getPosition()).toEqual(testObject.position.getValue(time)); @@ -198,6 +203,7 @@ defineSuite([ expect(l.getPixelOffset()).toEqual(testObject.label.pixelOffset.getValue(time)); expect(l.getScale()).toEqual(testObject.label.scale.getValue(time)); expect(l.getShow()).toEqual(testObject.label.show.getValue(time)); + expect(l.getTranslucencyByDistance()).toEqual(testObject.label.translucencyByDistance.getValue(time)); label.show = new ConstantProperty(false); visualizer.update(time); From 7f7dd599f0195440a95a0b6fadb26b72c87c646e Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Fri, 4 Oct 2013 08:43:03 -0400 Subject: [PATCH 08/10] Clipping billboards that have scale or translucency of 0.0 in the vertex shader. Minor cleanup in unit tests and Sandcastle example. Signed-off-by: Alex Wood --- Apps/Sandcastle/gallery/Labels.html | 18 ------------------ Source/Shaders/BillboardCollectionFS.glsl | 6 ------ Source/Shaders/BillboardCollectionVS.glsl | 12 ++++++++++-- Specs/Scene/BillboardCollectionSpec.js | 14 ++++---------- Specs/Scene/LabelCollectionSpec.js | 6 +----- 5 files changed, 15 insertions(+), 41 deletions(-) diff --git a/Apps/Sandcastle/gallery/Labels.html b/Apps/Sandcastle/gallery/Labels.html index 379c4da0fd3b..2a8794848092 100644 --- a/Apps/Sandcastle/gallery/Labels.html +++ b/Apps/Sandcastle/gallery/Labels.html @@ -102,24 +102,6 @@ text : 'Philadelphia', translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.0) }); - - // add a billboard to mark Philadelphia on the globe - var image = new Image(); - image.onload = function() { - var billboards = new Cesium.BillboardCollection(); - var textureAtlas = scene.getContext().createTextureAtlas({ - image : image - }); - billboards.setTextureAtlas(textureAtlas); - - billboards.add({ - position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.10, 39.57)), - imageIndex : 0 - }); - scene.getPrimitives().add(billboards); - }; - image.src = '../images/facility.gif'; - scene.getPrimitives().add(labels); } diff --git a/Source/Shaders/BillboardCollectionFS.glsl b/Source/Shaders/BillboardCollectionFS.glsl index 4e8d5546d8c4..46e9ad146425 100644 --- a/Source/Shaders/BillboardCollectionFS.glsl +++ b/Source/Shaders/BillboardCollectionFS.glsl @@ -4,7 +4,6 @@ varying vec2 v_textureCoordinates; #ifdef RENDER_FOR_PICK varying vec4 v_pickColor; -varying float v_pickTranslucency; #else varying vec4 v_color; #endif @@ -12,11 +11,6 @@ varying vec4 v_color; void main() { #ifdef RENDER_FOR_PICK - if (v_pickTranslucency == 0.0) - { - discard; - } - vec4 vertexColor = vec4(1.0, 1.0, 1.0, 1.0); #else vec4 vertexColor = v_color; diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index 119fa313d8b0..2b2405674e6a 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -21,7 +21,6 @@ varying vec2 v_textureCoordinates; #ifdef RENDER_FOR_PICK varying vec4 v_pickColor; -varying float v_pickTranslucency; #else varying vec4 v_color; #endif @@ -78,11 +77,21 @@ void main() #ifdef EYE_DISTANCE_SCALING scale *= getNearFarScalar(scaleByDistance, lengthSq); + // push vertex behind near plane for clipping + if (scale == 0.0) + { + positionEC.xyz *= scale; + } #endif float translucency = 1.0; #ifdef EYE_DISTANCE_TRANSLUCENCY translucency = getNearFarScalar(translucencyByDistance, lengthSq); + // push vertex behind near plane for clipping + if (translucency == 0.0) + { + positionEC.xyz *= translucency; + } #endif vec4 positionWC = czm_eyeToWindowCoordinates(positionEC); @@ -123,7 +132,6 @@ void main() #ifdef RENDER_FOR_PICK v_pickColor = pickColor; - v_pickTranslucency = translucency; #else v_color = color; v_color.a *= translucency; diff --git a/Specs/Scene/BillboardCollectionSpec.js b/Specs/Scene/BillboardCollectionSpec.js index fb656e048479..1b2295e3545f 100644 --- a/Specs/Scene/BillboardCollectionSpec.js +++ b/Specs/Scene/BillboardCollectionSpec.js @@ -240,10 +240,9 @@ defineSuite([ imageIndex : 0 }); - // verify basis ClearCommand.ALL.execute(context); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // camera at 1.0 above billboard, expect green pixel to be rendered, as scale is near 1.0 + var us = context.getUniformState(); var eye = new Cartesian3(0.0, 0.0, 1.0); var target = Cartesian3.ZERO; @@ -251,15 +250,13 @@ defineSuite([ us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); render(context, frameState, billboards); expect(context.readPixels()).toEqual([0, 255, 0, 255]); - // clear screen ClearCommand.ALL.execute(context); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // camera at 6.0 above billboard, expect no green pixels to be rendered, as scale is 0.0 + eye = new Cartesian3(0.0, 0.0, 6.0); us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); render(context, frameState, billboards); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // revert framestate us.update(context, createFrameState(createCamera(context))); }); @@ -275,10 +272,9 @@ defineSuite([ imageIndex : 0 }); - // verify basis ClearCommand.ALL.execute(context); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // camera at 1.0 above billboard, expect green pixel to be rendered, as translucency is near 1.0 + var us = context.getUniformState(); var eye = new Cartesian3(0.0, 0.0, 1.0); var target = Cartesian3.ZERO; @@ -286,15 +282,13 @@ defineSuite([ us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); render(context, frameState, billboards); expect(context.readPixels()).toEqual([0, 255, 0, 255]); - // clear screen ClearCommand.ALL.execute(context); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // camera at 6.0 above billboard, expect no green pixels to be rendered, as translucency is 0.0 + eye = new Cartesian3(0.0, 0.0, 6.0); us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); render(context, frameState, billboards); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // revert framestate us.update(context, createFrameState(createCamera(context))); }); diff --git a/Specs/Scene/LabelCollectionSpec.js b/Specs/Scene/LabelCollectionSpec.js index a1882b7e5665..110581ca7e72 100644 --- a/Specs/Scene/LabelCollectionSpec.js +++ b/Specs/Scene/LabelCollectionSpec.js @@ -654,10 +654,8 @@ defineSuite([ translucencyByDistance: new NearFarScalar(1.0, 1.0, 3.0, 0.0) }); - // verify basis ClearCommand.ALL.execute(context); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // camera at 1.0 above label, expect label to be rendered, as translucency is near 1.0 var us = context.getUniformState(); var eye = new Cartesian3(0.0, 0.0, 1.0); var target = Cartesian3.ZERO; @@ -665,15 +663,13 @@ defineSuite([ us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); render(context, frameState, labels); expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); - // clear screen ClearCommand.ALL.execute(context); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // camera at 6.0 above label, expect no pixels to be rendered, as translucency is 0.0 + eye = new Cartesian3(0.0, 0.0, 6.0); us.update(context, createFrameState(createCamera(context, eye, target, up, 0.1, 10.0))); render(context, frameState, labels); expect(context.readPixels()).toEqual([0, 0, 0, 0]); - // revert framestate us.update(context, createFrameState(createCamera(context))); }); From b4271679b5e1e5d9420ffc0845bb8e4332b5b2ac Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Fri, 4 Oct 2013 13:38:28 -0400 Subject: [PATCH 09/10] Explicit assignment to zero for Billboard vertex shader clipping of vertex with scale or translucency equal to 0. Signed-off-by: Alex Wood --- Source/Shaders/BillboardCollectionVS.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index 2b2405674e6a..09f9165f2071 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -80,7 +80,7 @@ void main() // push vertex behind near plane for clipping if (scale == 0.0) { - positionEC.xyz *= scale; + positionEC.xyz = vec3(0.0); } #endif @@ -90,7 +90,7 @@ void main() // push vertex behind near plane for clipping if (translucency == 0.0) { - positionEC.xyz *= translucency; + positionEC.xyz = vec3(0.0); } #endif From 348f501b4a0e1f8f12496c491117ab66eded839a Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Fri, 4 Oct 2013 13:59:58 -0400 Subject: [PATCH 10/10] Revised presentation in Label translucency Sandcastle example. Signed-off-by: Alex Wood --- Apps/Sandcastle/gallery/Labels.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Apps/Sandcastle/gallery/Labels.html b/Apps/Sandcastle/gallery/Labels.html index 2a8794848092..e9c5badf8d64 100644 --- a/Apps/Sandcastle/gallery/Labels.html +++ b/Apps/Sandcastle/gallery/Labels.html @@ -95,12 +95,13 @@ var labels = new Cesium.LabelCollection(); labels.add({ position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-73.94, 40.67)), - text : 'New York' + text : 'New York', + translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e8, 0.0) }); labels.add({ - position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.10, 39.57)), - text : 'Philadelphia', - translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.0) + position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-84.39, 33.75)), + text : 'Atlanta', + translucencyByDistance : new Cesium.NearFarScalar(1.5e5, 1.0, 1.5e7, 0.0) }); scene.getPrimitives().add(labels); }