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

### 1.46.1 - 2018-06-01
Expand Down
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,9 @@ define([
this._imageWidth = undefined;
this._imageHeight = undefined;

this._labelDimensions = undefined;
this._labelHorizontalOrigin = undefined;

var image = options.image;
var imageId = options.imageId;
if (defined(image)) {
Expand Down Expand Up @@ -210,7 +213,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
164 changes: 140 additions & 24 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 @@ -1020,6 +1033,9 @@ define([
var dimensions = billboardCollection._textureAtlas.texture.dimensions;
var imageHeight = Math.round(defaultValue(billboard.height, dimensions.y * height));
billboardCollection._maxSize = Math.max(billboardCollection._maxSize, imageHeight);
var labelHorizontalOrigin = defaultValue(billboard._labelHorizontalOrigin, -2);
labelHorizontalOrigin += 2;
var compressed3 = imageHeight * LEFT_SHIFT2 + labelHorizontalOrigin;

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

if (billboardCollection._instanced) {
i = billboard._index;
writer(i, compressed0, compressed1, compressed2, imageHeight);
writer(i, compressed0, compressed1, compressed2, compressed3);
} else {
i = billboard._index * 4;
writer(i + 0, compressed0, compressed1, compressed2, imageHeight);
writer(i + 1, compressed0, compressed1, compressed2, imageHeight);
writer(i + 2, compressed0, compressed1, compressed2, imageHeight);
writer(i + 3, compressed0, compressed1, compressed2, imageHeight);
writer(i + 0, compressed0, compressed1, compressed2, compressed3);
writer(i + 1, compressed0, compressed1, compressed2, compressed3);
writer(i + 2, compressed0, compressed1, compressed2, compressed3);
writer(i + 3, compressed0, compressed1, compressed2, compressed3);
}
}

Expand Down Expand Up @@ -1158,9 +1174,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 +1192,10 @@ define([
}

var disableDepthTestDistance = billboard.disableDepthTestDistance;
if (billboard.heightReference === HeightReference.CLAMP_TO_GROUND && disableDepthTestDistance === 0.0 && billboardCollection._scene.context.depthTexture) {
disableDepthTestDistance = 2000.0;
}

disableDepthTestDistance *= disableDepthTestDistance;
if (disableDepthTestDistance > 0.0) {
billboardCollection._shaderDisableDepthDistance = true;
Expand All @@ -1184,15 +1204,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 = billboardCollection._scene.context.depthTexture;
}
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 +1319,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 +1516,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 +1639,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 +1680,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 +1691,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 +1706,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 +1723,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 +1740,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 +1759,7 @@ define([
this._compiledShaderPixelOffsetScaleByDistance = this._shaderPixelOffsetScaleByDistance;
this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition;
this._compiledShaderDisableDepthDistance = this._shaderDisableDepthDistance;
this._compiledShaderClampToGround = this._shaderClampToGround;
}

var commandList = frameState.commandList;
Expand Down
Loading