Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix billboards when clamped to ground with depthTestAgainstTerrain #6621

Merged
merged 18 commits into from
Jun 21, 2018
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Change Log
##### Fixes :wrench:
* Fixed a bug causing crashes with custom vertex attributes on `Geometry` crossing the IDL. Attributes will be barycentrically interpolated. [#6644](https://github.com/AnalyticalGraphicsInc/cesium/pull/6644)
* Fixed a bug with Draco encoded i3dm tiles, and loading two Draco models with the same url. [#6668](https://github.com/AnalyticalGraphicsInc/cesium/issues/6668)
* Improved billboard and label rendering so they no longer sink into terrain when clamped to ground. [#6621](https://github.com/AnalyticalGraphicsInc/cesium/pull/6621)

### 1.46.1 - 2018-06-01

Expand Down
5 changes: 4 additions & 1 deletion Source/Scene/Billboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ define([
this._imageWidth = undefined;
this._imageHeight = undefined;

this._labelDimensions = undefined;

var image = options.image;
var imageId = options.imageId;
if (defined(image)) {
Expand Down Expand Up @@ -210,7 +212,8 @@ define([
var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = 13;
var DISTANCE_DISPLAY_CONDITION = Billboard.DISTANCE_DISPLAY_CONDITION = 14;
var DISABLE_DEPTH_DISTANCE = Billboard.DISABLE_DEPTH_DISTANCE = 15;
Billboard.NUMBER_OF_PROPERTIES = 16;
Billboard.TEXTURE_COORDINATE_BOUNDS = 16;
Billboard.NUMBER_OF_PROPERTIES = 17;

function makeDirty(billboard, propertyChanged) {
var billboardCollection = billboard._billboardCollection;
Expand Down
151 changes: 132 additions & 19 deletions Source/Scene/BillboardCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ define([
var SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX;
var TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX;
var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX;
var DISTANCE_DISPLAY_CONDITION_INDEX = Billboard.DISTANCE_DISPLAY_CONDITION_INDEX;
var DISTANCE_DISPLAY_CONDITION_INDEX = Billboard.DISTANCE_DISPLAY_CONDITION;
var DISABLE_DEPTH_DISTANCE = Billboard.DISABLE_DEPTH_DISTANCE;
var TEXTURE_COORDINATE_BOUNDS = Billboard.TEXTURE_COORDINATE_BOUNDS;
var NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES;

var attributeLocations;
Expand All @@ -99,8 +100,9 @@ define([
eyeOffset : 5, // 4 bytes free
scaleByDistance : 6,
pixelOffsetScaleByDistance : 7,
distanceDisplayConditionAndDisableDepth : 8,
a_batchId : 9
compressedAttribute3 : 8,
textureCoordinateBounds : 9,
a_batchId : 10
};

var attributeLocationsInstanced = {
Expand All @@ -113,8 +115,9 @@ define([
eyeOffset : 6, // texture range in w
scaleByDistance : 7,
pixelOffsetScaleByDistance : 8,
distanceDisplayConditionAndDisableDepth : 9,
a_batchId : 10
compressedAttribute3 : 9,
textureCoordinateBounds : 10,
a_batchId : 11
};

/**
Expand Down Expand Up @@ -208,6 +211,9 @@ define([
this._shaderDisableDepthDistance = false;
this._compiledShaderDisableDepthDistance = false;

this._shaderClampToGround = false;
this._compiledShaderClampToGround = false;

this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);

this._maxSize = 0.0;
Expand Down Expand Up @@ -302,7 +308,8 @@ define([
BufferUsage.STATIC_DRAW, // SCALE_BY_DISTANCE_INDEX
BufferUsage.STATIC_DRAW, // TRANSLUCENCY_BY_DISTANCE_INDEX
BufferUsage.STATIC_DRAW, // PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX
BufferUsage.STATIC_DRAW // DISTANCE_DISPLAY_CONDITION_INDEX
BufferUsage.STATIC_DRAW, // DISTANCE_DISPLAY_CONDITION_INDEX
BufferUsage.STATIC_DRAW // TEXTURE_COORDINATE_BOUNDS
];

this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints
Expand Down Expand Up @@ -732,10 +739,15 @@ define([
componentDatatype : ComponentDatatype.FLOAT,
usage : buffersUsage[PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX]
}, {
index : attributeLocations.distanceDisplayConditionAndDisableDepth,
componentsPerAttribute : 3,
index : attributeLocations.compressedAttribute3,
componentsPerAttribute : 4,
componentDatatype : ComponentDatatype.FLOAT,
usage : buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX]
}, {
index : attributeLocations.textureCoordinateBounds,
componentsPerAttribute : 4,
componentDatatype : ComponentDatatype.FLOAT,
usage : buffersUsage[TEXTURE_COORDINATE_BOUNDS]
}];

// Instancing requires one non-instanced attribute.
Expand Down Expand Up @@ -818,6 +830,7 @@ define([
var UPPER_BOUND = 32768.0; // 2^15

var LEFT_SHIFT16 = 65536.0; // 2^16
var LEFT_SHIFT12 = 4096.0; // 2^12
var LEFT_SHIFT8 = 256.0; // 2^8
var LEFT_SHIFT7 = 128.0;
var LEFT_SHIFT5 = 32.0;
Expand Down Expand Up @@ -1158,9 +1171,9 @@ define([
}
}

function writeDistanceDisplayConditionAndDepthDisable(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) {
function writeCompressedAttribute3(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) {
var i;
var writer = vafWriters[attributeLocations.distanceDisplayConditionAndDisableDepth];
var writer = vafWriters[attributeLocations.compressedAttribute3];
var near = 0.0;
var far = Number.MAX_VALUE;

Expand All @@ -1176,6 +1189,10 @@ define([
}

var disableDepthTestDistance = billboard.disableDepthTestDistance;
if (billboard.heightReference === HeightReference.CLAMP_TO_GROUND && disableDepthTestDistance === 0.0) {
disableDepthTestDistance = 2000.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be configurable at the scene level? I think there are other billboard/label/depth-ish options there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's configurable by setting disableDepthTestDistance to a different value

}

disableDepthTestDistance *= disableDepthTestDistance;
if (disableDepthTestDistance > 0.0) {
billboardCollection._shaderDisableDepthDistance = true;
Expand All @@ -1184,15 +1201,89 @@ define([
}
}

var imageHeight;
var imageWidth;

if (!defined(billboard._labelDimensions)) {
var height = 0;
var width = 0;
var index = billboard._imageIndex;
if (index !== -1) {
var imageRectangle = textureAtlasCoordinates[index];

//>>includeStart('debug', pragmas.debug);
if (!defined(imageRectangle)) {
throw new DeveloperError('Invalid billboard image index: ' + index);
}
//>>includeEnd('debug');

height = imageRectangle.height;
width = imageRectangle.width;
}

imageHeight = Math.round(defaultValue(billboard.height, billboardCollection._textureAtlas.texture.dimensions.y * height));

var textureWidth = billboardCollection._textureAtlas.texture.width;
imageWidth = Math.round(defaultValue(billboard.width, textureWidth * width));
} else {
imageWidth = billboard._labelDimensions.x;
imageHeight = billboard._labelDimensions.y;
}

var w = Math.floor(CesiumMath.clamp(imageWidth, 0.0, LEFT_SHIFT12));
var h = Math.floor(CesiumMath.clamp(imageHeight, 0.0, LEFT_SHIFT12));
var dimensions = w * LEFT_SHIFT12 + h;

if (billboardCollection._instanced) {
i = billboard._index;
writer(i, near, far, disableDepthTestDistance, dimensions);
} else {
i = billboard._index * 4;
writer(i + 0, near, far, disableDepthTestDistance, dimensions);
writer(i + 1, near, far, disableDepthTestDistance, dimensions);
writer(i + 2, near, far, disableDepthTestDistance, dimensions);
writer(i + 3, near, far, disableDepthTestDistance, dimensions);
}
}

function writeTextureCoordinateBounds(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) {
if (billboard.heightReference === HeightReference.CLAMP_TO_GROUND) {
billboardCollection._shaderClampToGround = true;
}
var i;
var writer = vafWriters[attributeLocations.textureCoordinateBounds];

var minX = 0;
var minY = 0;
var width = 0;
var height = 0;
var index = billboard._imageIndex;
if (index !== -1) {
var imageRectangle = textureAtlasCoordinates[index];

//>>includeStart('debug', pragmas.debug);
if (!defined(imageRectangle)) {
throw new DeveloperError('Invalid billboard image index: ' + index);
}
//>>includeEnd('debug');

minX = imageRectangle.x;
minY = imageRectangle.y;
width = imageRectangle.width;
height = imageRectangle.height;
}
var maxX = minX + width;
var maxY = minY + height;

if (billboardCollection._instanced) {
i = billboard._index;
writer(i, near, far, disableDepthTestDistance);
writer(i, minX, minY, maxX, maxY);
} else {
i = billboard._index * 4;
writer(i + 0, near, far, disableDepthTestDistance);
writer(i + 1, near, far, disableDepthTestDistance);
writer(i + 2, near, far, disableDepthTestDistance);
writer(i + 3, near, far, disableDepthTestDistance);
writer(i + 0, minX, minY, maxX, maxY);
writer(i + 1, minX, minY, maxX, maxY);
writer(i + 2, minX, minY, maxX, maxY);
writer(i + 3, minX, minY, maxX, maxY);
}
}

Expand Down Expand Up @@ -1225,7 +1316,8 @@ define([
writeEyeOffset(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writePixelOffsetScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeDistanceDisplayConditionAndDepthDisable(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeCompressedAttribute3(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeTextureCoordinateBounds(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeBatchId(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
}

Expand Down Expand Up @@ -1421,8 +1513,12 @@ define([
writers.push(writePixelOffsetScaleByDistance);
}

if (properties[DISTANCE_DISPLAY_CONDITION_INDEX] || properties[DISABLE_DEPTH_DISTANCE]) {
writers.push(writeDistanceDisplayConditionAndDepthDisable);
if (properties[DISTANCE_DISPLAY_CONDITION_INDEX] || properties[DISABLE_DEPTH_DISTANCE] || properties[IMAGE_INDEX_INDEX] || properties[POSITION_INDEX]) {
writers.push(writeCompressedAttribute3);
}

if (properties[IMAGE_INDEX_INDEX] || properties[POSITION_INDEX]) {
writers.push(writeTextureCoordinateBounds);
}

var numWriters = writers.length;
Expand Down Expand Up @@ -1540,7 +1636,8 @@ define([
(this._shaderTranslucencyByDistance !== this._compiledShaderTranslucencyByDistance) ||
(this._shaderPixelOffsetScaleByDistance !== this._compiledShaderPixelOffsetScaleByDistance) ||
(this._shaderDistanceDisplayCondition !== this._compiledShaderDistanceDisplayCondition) ||
(this._shaderDisableDepthDistance !== this._compiledShaderDisableDepthDistance)) {
(this._shaderDisableDepthDistance !== this._compiledShaderDisableDepthDistance) ||
(this._shaderClampToGround !== this._compiledShaderClampToGround)) {

vsSource = BillboardCollectionVS;
fsSource = BillboardCollectionFS;
Expand Down Expand Up @@ -1580,6 +1677,9 @@ define([
if (this._shaderDisableDepthDistance) {
vs.defines.push('DISABLE_DEPTH_DISTANCE');
}
if (this._shaderClampToGround) {
vs.defines.push('CLAMP_TO_GROUND');
}

var vectorFragDefine = defined(this._batchTable) ? 'VECTOR_TILE' : '';

Expand All @@ -1588,6 +1688,9 @@ define([
defines : ['OPAQUE', vectorFragDefine],
sources : [fsSource]
});
if (this._shaderClampToGround) {
fs.defines.push('CLAMP_TO_GROUND');
}
this._sp = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._sp,
Expand All @@ -1600,6 +1703,9 @@ define([
defines : ['TRANSLUCENT', vectorFragDefine],
sources : [fsSource]
});
if (this._shaderClampToGround) {
fs.defines.push('CLAMP_TO_GROUND');
}
this._spTranslucent = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._spTranslucent,
Expand All @@ -1614,6 +1720,9 @@ define([
defines : [vectorFragDefine],
sources : [fsSource]
});
if (this._shaderClampToGround) {
fs.defines.push('CLAMP_TO_GROUND');
}
this._sp = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._sp,
Expand All @@ -1628,6 +1737,9 @@ define([
defines : [vectorFragDefine],
sources : [fsSource]
});
if (this._shaderClampToGround) {
fs.defines.push('CLAMP_TO_GROUND');
}
this._spTranslucent = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._spTranslucent,
Expand All @@ -1644,6 +1756,7 @@ define([
this._compiledShaderPixelOffsetScaleByDistance = this._shaderPixelOffsetScaleByDistance;
this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition;
this._compiledShaderDisableDepthDistance = this._shaderDisableDepthDistance;
this._compiledShaderClampToGround = this._shaderClampToGround;
}

var commandList = frameState.commandList;
Expand Down
19 changes: 14 additions & 5 deletions Source/Scene/LabelCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ define([
billboard = labelCollection._billboardCollection.add({
collection : labelCollection
});
billboard._labelDimensions = new Cartesian2();
}
glyph.billboard = billboard;
}
Expand Down Expand Up @@ -306,10 +307,9 @@ define([
var glyphLength = glyphs.length;

var backgroundBillboard = label._backgroundBillboard;
var backgroundPadding = scratchBackgroundPadding;
Cartesian2.clone(
var backgroundPadding = Cartesian2.clone(
(defined(backgroundBillboard) ? label._backgroundPadding : Cartesian2.ZERO),
backgroundPadding);
scratchBackgroundPadding);

for (glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {
if (text.charAt(glyphIndex) === '\n') {
Expand Down Expand Up @@ -341,6 +341,13 @@ define([
var widthOffset = calculateWidthOffset(lineWidth, horizontalOrigin, backgroundPadding);
var lineSpacing = defaultLineSpacingPercent * maxLineHeight;
var otherLinesHeight = lineSpacing * (numberOfLines - 1);
var totalLineWidth = maxLineWidth;
var totalLineHeight = maxLineHeight + otherLinesHeight;

if (defined(backgroundBillboard)) {
totalLineWidth += (backgroundPadding.x * 2);
totalLineHeight += (backgroundPadding.y * 2);
}

glyphPixelOffset.x = widthOffset * scale * resolutionScale;
glyphPixelOffset.y = 0;
Expand Down Expand Up @@ -371,6 +378,8 @@ define([

if (defined(glyph.billboard)) {
glyph.billboard._setTranslate(glyphPixelOffset);
glyph.billboard._labelDimensions.x = totalLineWidth;
glyph.billboard._labelDimensions.y = totalLineHeight;
}

//Compute the next x offset taking into acocunt the kerning performed
Expand Down Expand Up @@ -405,8 +414,8 @@ define([
}
glyphPixelOffset.y = glyphPixelOffset.y * scale * resolutionScale;

backgroundBillboard.width = maxLineWidth + (backgroundPadding.x * 2);
backgroundBillboard.height = maxLineHeight + otherLinesHeight + (backgroundPadding.y * 2);
backgroundBillboard.width = totalLineWidth;
backgroundBillboard.height = totalLineHeight;
backgroundBillboard._setTranslate(glyphPixelOffset);
}
}
Expand Down
Loading