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
6 changes: 5 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,9 @@ 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.DIMENSIONS = 17;
Billboard.NUMBER_OF_PROPERTIES = 18;

function makeDirty(billboard, propertyChanged) {
var billboardCollection = billboard._billboardCollection;
Expand Down
154 changes: 148 additions & 6 deletions Source/Scene/BillboardCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ 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 DIMENSIONS = Billboard.DIMENSIONS;
var NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES;

var attributeLocations;
Expand All @@ -100,7 +102,9 @@ define([
scaleByDistance : 6,
pixelOffsetScaleByDistance : 7,
distanceDisplayConditionAndDisableDepth : 8,
a_batchId : 9
textureCoordinateBounds : 9,
dimensions : 10,
a_batchId : 11
};

var attributeLocationsInstanced = {
Expand All @@ -114,7 +118,9 @@ define([
scaleByDistance : 7,
pixelOffsetScaleByDistance : 8,
distanceDisplayConditionAndDisableDepth : 9,
a_batchId : 10
textureCoordinateBounds : 10,
dimensions : 11,
a_batchId : 12
};

/**
Expand Down Expand Up @@ -208,6 +214,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 +311,9 @@ 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
BufferUsage.STATIC_DRAW // DIMENSIONS
];

this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints
Expand Down Expand Up @@ -736,6 +747,16 @@ define([
componentsPerAttribute : 3,
componentDatatype : ComponentDatatype.FLOAT,
usage : buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX]
}, {
index : attributeLocations.textureCoordinateBounds,
componentsPerAttribute : 4,
componentDatatype : ComponentDatatype.FLOAT,
usage : buffersUsage[TEXTURE_COORDINATE_BOUNDS]
}, {
index : attributeLocations.dimensions,
componentsPerAttribute : 2,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there anyway to pack this into one component and perhaps store as z in DISTANCE_DISPLAY_CONDITION_INDEX? Haven't looked closely, but perhaps precision requirements are not stiff here and fewer bits can be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to pack a Cartesian2 into one float? I'm not quite sure how to do this

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

There are no bit-wise operators in GLSL but you can shift bits by multiplying powers of 2. See any of the writeCompressedAttrib* functions. So if you want to pack a Cartesian2 into a float, you'll have 12 bits for each component. Is that enough precision? It would look something like this for packing:

var LEFT_SHIFT12 = Math.pow(2.0, 12.0);
var width = Math.floor(Math.clamp(width, 0.0, LEFT_SHIFT12));
var height = Math.floor(Math.clamp(height, 0.0, LEFT_SHIFT12));
var dimensions = width * LEFT_SHIFT12 + height;

Then, reverse it in the vertex shader to unpack.

componentDatatype : ComponentDatatype.FLOAT,
usage : buffersUsage[DIMENSIONS]
}];

// Instancing requires one non-instanced attribute.
Expand Down Expand Up @@ -1176,6 +1197,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 @@ -1196,6 +1221,96 @@ define([
}
}

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, minX, minY, maxX, maxY);
} else {
i = billboard._index * 4;
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);
}
}

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

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;
}

var dimensions = billboardCollection._textureAtlas.texture.dimensions;
imageHeight = Math.round(defaultValue(billboard.height, 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;
}

if (billboardCollection._instanced) {
i = billboard._index;
writer(i, imageWidth, imageHeight);
} else {
i = billboard._index * 2;
writer(i + 0, imageWidth, imageHeight);
writer(i + 1, imageWidth, imageHeight);
writer(i + 2, imageWidth, imageHeight);
writer(i + 3, imageWidth, imageHeight);
}
}

function writeBatchId(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) {
if (!defined(billboardCollection._batchTable)) {
return;
Expand Down Expand Up @@ -1226,6 +1341,8 @@ define([
writeScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writePixelOffsetScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeDistanceDisplayConditionAndDepthDisable(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeTextureCoordinateBounds(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeDimensions(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
writeBatchId(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
}

Expand Down Expand Up @@ -1421,10 +1538,18 @@ define([
writers.push(writePixelOffsetScaleByDistance);
}

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

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

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

var numWriters = writers.length;
vafWriters = this._vaf.writers;

Expand Down Expand Up @@ -1540,7 +1665,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 +1706,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 +1717,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 +1732,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 +1749,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 +1766,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 +1785,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