Skip to content

Commit 0a23971

Browse files
authored
Merge pull request #6621 from AnalyticalGraphicsInc/billboard-depth-test
Fix billboards when clamped to ground with depthTestAgainstTerrain
2 parents 21dafa7 + 4c3da3b commit 0a23971

6 files changed

+339
-90
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Change Log
2424
* 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)
2525
* Fixed terrain clipping when the camera was close to flat terrain and was using logarithmic depth. [#6701](https://github.com/AnalyticalGraphicsInc/cesium/pull/6701)
2626
* Fixed KML bug that constantly requested the same image if it failed to load. [#6710](https://github.com/AnalyticalGraphicsInc/cesium/pull/6710)
27+
* Improved billboard and label rendering so they no longer sink into terrain when clamped to ground. [#6621](https://github.com/AnalyticalGraphicsInc/cesium/pull/6621)
2728
* Fixed an issue where KMLs containing a `colorMode` of `random` could return the exact same color on successive calls to `Color.fromRandom()`.
2829

2930
### 1.46.1 - 2018-06-01

Source/Scene/Billboard.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ define([
159159
this._imageWidth = undefined;
160160
this._imageHeight = undefined;
161161

162+
this._labelDimensions = undefined;
163+
this._labelHorizontalOrigin = undefined;
164+
162165
var image = options.image;
163166
var imageId = options.imageId;
164167
if (defined(image)) {
@@ -210,7 +213,8 @@ define([
210213
var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = 13;
211214
var DISTANCE_DISPLAY_CONDITION = Billboard.DISTANCE_DISPLAY_CONDITION = 14;
212215
var DISABLE_DEPTH_DISTANCE = Billboard.DISABLE_DEPTH_DISTANCE = 15;
213-
Billboard.NUMBER_OF_PROPERTIES = 16;
216+
Billboard.TEXTURE_COORDINATE_BOUNDS = 16;
217+
Billboard.NUMBER_OF_PROPERTIES = 17;
214218

215219
function makeDirty(billboard, propertyChanged) {
216220
var billboardCollection = billboard._billboardCollection;

Source/Scene/BillboardCollection.js

+140-24
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ define([
8484
var SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX;
8585
var TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX;
8686
var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX;
87-
var DISTANCE_DISPLAY_CONDITION_INDEX = Billboard.DISTANCE_DISPLAY_CONDITION_INDEX;
87+
var DISTANCE_DISPLAY_CONDITION_INDEX = Billboard.DISTANCE_DISPLAY_CONDITION;
8888
var DISABLE_DEPTH_DISTANCE = Billboard.DISABLE_DEPTH_DISTANCE;
89+
var TEXTURE_COORDINATE_BOUNDS = Billboard.TEXTURE_COORDINATE_BOUNDS;
8990
var NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES;
9091

9192
var attributeLocations;
@@ -99,8 +100,9 @@ define([
99100
eyeOffset : 5, // 4 bytes free
100101
scaleByDistance : 6,
101102
pixelOffsetScaleByDistance : 7,
102-
distanceDisplayConditionAndDisableDepth : 8,
103-
a_batchId : 9
103+
compressedAttribute3 : 8,
104+
textureCoordinateBounds : 9,
105+
a_batchId : 10
104106
};
105107

106108
var attributeLocationsInstanced = {
@@ -113,8 +115,9 @@ define([
113115
eyeOffset : 6, // texture range in w
114116
scaleByDistance : 7,
115117
pixelOffsetScaleByDistance : 8,
116-
distanceDisplayConditionAndDisableDepth : 9,
117-
a_batchId : 10
118+
compressedAttribute3 : 9,
119+
textureCoordinateBounds : 10,
120+
a_batchId : 11
118121
};
119122

120123
/**
@@ -208,6 +211,9 @@ define([
208211
this._shaderDisableDepthDistance = false;
209212
this._compiledShaderDisableDepthDistance = false;
210213

214+
this._shaderClampToGround = false;
215+
this._compiledShaderClampToGround = false;
216+
211217
this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);
212218

213219
this._maxSize = 0.0;
@@ -302,7 +308,8 @@ define([
302308
BufferUsage.STATIC_DRAW, // SCALE_BY_DISTANCE_INDEX
303309
BufferUsage.STATIC_DRAW, // TRANSLUCENCY_BY_DISTANCE_INDEX
304310
BufferUsage.STATIC_DRAW, // PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX
305-
BufferUsage.STATIC_DRAW // DISTANCE_DISPLAY_CONDITION_INDEX
311+
BufferUsage.STATIC_DRAW, // DISTANCE_DISPLAY_CONDITION_INDEX
312+
BufferUsage.STATIC_DRAW // TEXTURE_COORDINATE_BOUNDS
306313
];
307314

308315
this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints
@@ -732,10 +739,15 @@ define([
732739
componentDatatype : ComponentDatatype.FLOAT,
733740
usage : buffersUsage[PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX]
734741
}, {
735-
index : attributeLocations.distanceDisplayConditionAndDisableDepth,
736-
componentsPerAttribute : 3,
742+
index : attributeLocations.compressedAttribute3,
743+
componentsPerAttribute : 4,
737744
componentDatatype : ComponentDatatype.FLOAT,
738745
usage : buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX]
746+
}, {
747+
index : attributeLocations.textureCoordinateBounds,
748+
componentsPerAttribute : 4,
749+
componentDatatype : ComponentDatatype.FLOAT,
750+
usage : buffersUsage[TEXTURE_COORDINATE_BOUNDS]
739751
}];
740752

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

820832
var LEFT_SHIFT16 = 65536.0; // 2^16
833+
var LEFT_SHIFT12 = 4096.0; // 2^12
821834
var LEFT_SHIFT8 = 256.0; // 2^8
822835
var LEFT_SHIFT7 = 128.0;
823836
var LEFT_SHIFT5 = 32.0;
@@ -1020,6 +1033,9 @@ define([
10201033
var dimensions = billboardCollection._textureAtlas.texture.dimensions;
10211034
var imageHeight = Math.round(defaultValue(billboard.height, dimensions.y * height));
10221035
billboardCollection._maxSize = Math.max(billboardCollection._maxSize, imageHeight);
1036+
var labelHorizontalOrigin = defaultValue(billboard._labelHorizontalOrigin, -2);
1037+
labelHorizontalOrigin += 2;
1038+
var compressed3 = imageHeight * LEFT_SHIFT2 + labelHorizontalOrigin;
10231039

10241040
var red = Color.floatToByte(color.red);
10251041
var green = Color.floatToByte(color.green);
@@ -1036,13 +1052,13 @@ define([
10361052

10371053
if (billboardCollection._instanced) {
10381054
i = billboard._index;
1039-
writer(i, compressed0, compressed1, compressed2, imageHeight);
1055+
writer(i, compressed0, compressed1, compressed2, compressed3);
10401056
} else {
10411057
i = billboard._index * 4;
1042-
writer(i + 0, compressed0, compressed1, compressed2, imageHeight);
1043-
writer(i + 1, compressed0, compressed1, compressed2, imageHeight);
1044-
writer(i + 2, compressed0, compressed1, compressed2, imageHeight);
1045-
writer(i + 3, compressed0, compressed1, compressed2, imageHeight);
1058+
writer(i + 0, compressed0, compressed1, compressed2, compressed3);
1059+
writer(i + 1, compressed0, compressed1, compressed2, compressed3);
1060+
writer(i + 2, compressed0, compressed1, compressed2, compressed3);
1061+
writer(i + 3, compressed0, compressed1, compressed2, compressed3);
10461062
}
10471063
}
10481064

@@ -1158,9 +1174,9 @@ define([
11581174
}
11591175
}
11601176

1161-
function writeDistanceDisplayConditionAndDepthDisable(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) {
1177+
function writeCompressedAttribute3(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) {
11621178
var i;
1163-
var writer = vafWriters[attributeLocations.distanceDisplayConditionAndDisableDepth];
1179+
var writer = vafWriters[attributeLocations.compressedAttribute3];
11641180
var near = 0.0;
11651181
var far = Number.MAX_VALUE;
11661182

@@ -1176,6 +1192,10 @@ define([
11761192
}
11771193

11781194
var disableDepthTestDistance = billboard.disableDepthTestDistance;
1195+
if (billboard.heightReference === HeightReference.CLAMP_TO_GROUND && disableDepthTestDistance === 0.0 && billboardCollection._scene.context.depthTexture) {
1196+
disableDepthTestDistance = 2000.0;
1197+
}
1198+
11791199
disableDepthTestDistance *= disableDepthTestDistance;
11801200
if (disableDepthTestDistance > 0.0) {
11811201
billboardCollection._shaderDisableDepthDistance = true;
@@ -1184,15 +1204,89 @@ define([
11841204
}
11851205
}
11861206

1207+
var imageHeight;
1208+
var imageWidth;
1209+
1210+
if (!defined(billboard._labelDimensions)) {
1211+
var height = 0;
1212+
var width = 0;
1213+
var index = billboard._imageIndex;
1214+
if (index !== -1) {
1215+
var imageRectangle = textureAtlasCoordinates[index];
1216+
1217+
//>>includeStart('debug', pragmas.debug);
1218+
if (!defined(imageRectangle)) {
1219+
throw new DeveloperError('Invalid billboard image index: ' + index);
1220+
}
1221+
//>>includeEnd('debug');
1222+
1223+
height = imageRectangle.height;
1224+
width = imageRectangle.width;
1225+
}
1226+
1227+
imageHeight = Math.round(defaultValue(billboard.height, billboardCollection._textureAtlas.texture.dimensions.y * height));
1228+
1229+
var textureWidth = billboardCollection._textureAtlas.texture.width;
1230+
imageWidth = Math.round(defaultValue(billboard.width, textureWidth * width));
1231+
} else {
1232+
imageWidth = billboard._labelDimensions.x;
1233+
imageHeight = billboard._labelDimensions.y;
1234+
}
1235+
1236+
var w = Math.floor(CesiumMath.clamp(imageWidth, 0.0, LEFT_SHIFT12));
1237+
var h = Math.floor(CesiumMath.clamp(imageHeight, 0.0, LEFT_SHIFT12));
1238+
var dimensions = w * LEFT_SHIFT12 + h;
1239+
1240+
if (billboardCollection._instanced) {
1241+
i = billboard._index;
1242+
writer(i, near, far, disableDepthTestDistance, dimensions);
1243+
} else {
1244+
i = billboard._index * 4;
1245+
writer(i + 0, near, far, disableDepthTestDistance, dimensions);
1246+
writer(i + 1, near, far, disableDepthTestDistance, dimensions);
1247+
writer(i + 2, near, far, disableDepthTestDistance, dimensions);
1248+
writer(i + 3, near, far, disableDepthTestDistance, dimensions);
1249+
}
1250+
}
1251+
1252+
function writeTextureCoordinateBounds(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) {
1253+
if (billboard.heightReference === HeightReference.CLAMP_TO_GROUND) {
1254+
billboardCollection._shaderClampToGround = billboardCollection._scene.context.depthTexture;
1255+
}
1256+
var i;
1257+
var writer = vafWriters[attributeLocations.textureCoordinateBounds];
1258+
1259+
var minX = 0;
1260+
var minY = 0;
1261+
var width = 0;
1262+
var height = 0;
1263+
var index = billboard._imageIndex;
1264+
if (index !== -1) {
1265+
var imageRectangle = textureAtlasCoordinates[index];
1266+
1267+
//>>includeStart('debug', pragmas.debug);
1268+
if (!defined(imageRectangle)) {
1269+
throw new DeveloperError('Invalid billboard image index: ' + index);
1270+
}
1271+
//>>includeEnd('debug');
1272+
1273+
minX = imageRectangle.x;
1274+
minY = imageRectangle.y;
1275+
width = imageRectangle.width;
1276+
height = imageRectangle.height;
1277+
}
1278+
var maxX = minX + width;
1279+
var maxY = minY + height;
1280+
11871281
if (billboardCollection._instanced) {
11881282
i = billboard._index;
1189-
writer(i, near, far, disableDepthTestDistance);
1283+
writer(i, minX, minY, maxX, maxY);
11901284
} else {
11911285
i = billboard._index * 4;
1192-
writer(i + 0, near, far, disableDepthTestDistance);
1193-
writer(i + 1, near, far, disableDepthTestDistance);
1194-
writer(i + 2, near, far, disableDepthTestDistance);
1195-
writer(i + 3, near, far, disableDepthTestDistance);
1286+
writer(i + 0, minX, minY, maxX, maxY);
1287+
writer(i + 1, minX, minY, maxX, maxY);
1288+
writer(i + 2, minX, minY, maxX, maxY);
1289+
writer(i + 3, minX, minY, maxX, maxY);
11961290
}
11971291
}
11981292

@@ -1225,7 +1319,8 @@ define([
12251319
writeEyeOffset(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
12261320
writeScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
12271321
writePixelOffsetScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
1228-
writeDistanceDisplayConditionAndDepthDisable(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
1322+
writeCompressedAttribute3(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
1323+
writeTextureCoordinateBounds(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
12291324
writeBatchId(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard);
12301325
}
12311326

@@ -1421,8 +1516,12 @@ define([
14211516
writers.push(writePixelOffsetScaleByDistance);
14221517
}
14231518

1424-
if (properties[DISTANCE_DISPLAY_CONDITION_INDEX] || properties[DISABLE_DEPTH_DISTANCE]) {
1425-
writers.push(writeDistanceDisplayConditionAndDepthDisable);
1519+
if (properties[DISTANCE_DISPLAY_CONDITION_INDEX] || properties[DISABLE_DEPTH_DISTANCE] || properties[IMAGE_INDEX_INDEX] || properties[POSITION_INDEX]) {
1520+
writers.push(writeCompressedAttribute3);
1521+
}
1522+
1523+
if (properties[IMAGE_INDEX_INDEX] || properties[POSITION_INDEX]) {
1524+
writers.push(writeTextureCoordinateBounds);
14261525
}
14271526

14281527
var numWriters = writers.length;
@@ -1540,7 +1639,8 @@ define([
15401639
(this._shaderTranslucencyByDistance !== this._compiledShaderTranslucencyByDistance) ||
15411640
(this._shaderPixelOffsetScaleByDistance !== this._compiledShaderPixelOffsetScaleByDistance) ||
15421641
(this._shaderDistanceDisplayCondition !== this._compiledShaderDistanceDisplayCondition) ||
1543-
(this._shaderDisableDepthDistance !== this._compiledShaderDisableDepthDistance)) {
1642+
(this._shaderDisableDepthDistance !== this._compiledShaderDisableDepthDistance) ||
1643+
(this._shaderClampToGround !== this._compiledShaderClampToGround)) {
15441644

15451645
vsSource = BillboardCollectionVS;
15461646
fsSource = BillboardCollectionFS;
@@ -1580,6 +1680,9 @@ define([
15801680
if (this._shaderDisableDepthDistance) {
15811681
vs.defines.push('DISABLE_DEPTH_DISTANCE');
15821682
}
1683+
if (this._shaderClampToGround) {
1684+
vs.defines.push('CLAMP_TO_GROUND');
1685+
}
15831686

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

@@ -1588,6 +1691,9 @@ define([
15881691
defines : ['OPAQUE', vectorFragDefine],
15891692
sources : [fsSource]
15901693
});
1694+
if (this._shaderClampToGround) {
1695+
fs.defines.push('CLAMP_TO_GROUND');
1696+
}
15911697
this._sp = ShaderProgram.replaceCache({
15921698
context : context,
15931699
shaderProgram : this._sp,
@@ -1600,6 +1706,9 @@ define([
16001706
defines : ['TRANSLUCENT', vectorFragDefine],
16011707
sources : [fsSource]
16021708
});
1709+
if (this._shaderClampToGround) {
1710+
fs.defines.push('CLAMP_TO_GROUND');
1711+
}
16031712
this._spTranslucent = ShaderProgram.replaceCache({
16041713
context : context,
16051714
shaderProgram : this._spTranslucent,
@@ -1614,6 +1723,9 @@ define([
16141723
defines : [vectorFragDefine],
16151724
sources : [fsSource]
16161725
});
1726+
if (this._shaderClampToGround) {
1727+
fs.defines.push('CLAMP_TO_GROUND');
1728+
}
16171729
this._sp = ShaderProgram.replaceCache({
16181730
context : context,
16191731
shaderProgram : this._sp,
@@ -1628,6 +1740,9 @@ define([
16281740
defines : [vectorFragDefine],
16291741
sources : [fsSource]
16301742
});
1743+
if (this._shaderClampToGround) {
1744+
fs.defines.push('CLAMP_TO_GROUND');
1745+
}
16311746
this._spTranslucent = ShaderProgram.replaceCache({
16321747
context : context,
16331748
shaderProgram : this._spTranslucent,
@@ -1644,6 +1759,7 @@ define([
16441759
this._compiledShaderPixelOffsetScaleByDistance = this._shaderPixelOffsetScaleByDistance;
16451760
this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition;
16461761
this._compiledShaderDisableDepthDistance = this._shaderDisableDepthDistance;
1762+
this._compiledShaderClampToGround = this._shaderClampToGround;
16471763
}
16481764

16491765
var commandList = frameState.commandList;

0 commit comments

Comments
 (0)